Beispiel #1
0
    public void PumpEvents(double deltaSeconds)
    {
        SetTitle();
        Sdl2Events.ProcessEvents();
        var snapshot = _window.PumpEvents();

        if (_window != null)
        {
            if (_pendingCursorUpdate.HasValue && _window.Focused)
            {
                using (PerfTracker.FrameEvent("3 Warping mouse"))
                {
                    Sdl2Native.SDL_WarpMouseInWindow(
                        _window.SdlWindowHandle,
                        (int)_pendingCursorUpdate.Value.X,
                        (int)_pendingCursorUpdate.Value.Y);

                    _pendingCursorUpdate = null;
                }
            }

            using (PerfTracker.FrameEvent("4 Raising input event"))
                Raise(new InputEvent(deltaSeconds, snapshot, _window.MouseDelta));
        }
    }
Beispiel #2
0
        void OnSlowClock(SlowClockEvent e)
        {
            if (_isSorting)
            {
                SortingUpdate(e);
                return;
            }

            using var _ = PerfTracker.FrameEvent("5.1 Update tilemap");

            if (_fullUpdate)
            {
                for (int j = 0; j < _mapData.Height; j++)
                {
                    for (int i = 0; i < _mapData.Width; i++)
                    {
                        int index = j * _mapData.Width + i;
                        SetTile(index, index, e.FrameCount);
                    }
                }

                _fullUpdate = false;
            }
            else
            {
                foreach (var index in _tilemap.AnimatedTiles)
                {
                    SetTile(index, index, e.FrameCount);
                }
            }
        }
Beispiel #3
0
    void Update(bool frameChanged)
    {
        if (frameChanged)
        {
            _dirty.UnionWith(_tilemap.AnimatedTiles);
        }

        if (_fullUpdate)
        {
            using var _ = PerfTracker.FrameEvent("5.1 Update tilemap");
            for (int j = 0; j < _logicalMap.Height; j++)
            {
                for (int i = 0; i < _logicalMap.Width; i++)
                {
                    int index = j * _logicalMap.Width + i;
                    SetTile(index, index, _frameCount);
                }
            }

            _fullUpdate = false;
        }
        else if (_dirty.Count > 0)
        {
            foreach (var index in _dirty)
            {
                SetTile(index, index, _frameCount);
            }
        }
        _dirty.Clear();
    }
Beispiel #4
0
        void SortingUpdate(SlowClockEvent e)
        {
            using var _ = PerfTracker.FrameEvent("5.1 Update tilemap (sorting)");

            foreach (var list in _tilesByDistance.Values)
            {
                list.Clear();
            }

            var scene = Resolve <ISceneManager>().ActiveScene;
            var cameraTilePosition = scene.Camera.Position;

            var map = Resolve <IMapManager>().Current;

            if (map != null)
            {
                cameraTilePosition /= map.TileSize;
            }

            int cameraTileX = (int)cameraTilePosition.X;
            int cameraTileY = (int)cameraTilePosition.Y;

            for (int j = 0; j < _mapData.Height; j++)
            {
                for (int i = 0; i < _mapData.Width; i++)
                {
                    int distance = Math.Abs(j - cameraTileY) + Math.Abs(i - cameraTileX);
                    if (!_tilesByDistance.TryGetValue(distance, out var list))
                    {
                        list = new List <int>();
                        _tilesByDistance[distance] = list;
                    }

                    int index = j * _mapData.Width + i;
                    list.Add(index);
                }
            }

            int order = 0;

            foreach (var distance in _tilesByDistance.OrderByDescending(x => x.Key).ToList())
            {
                if (distance.Value.Count == 0)
                {
                    _tilesByDistance.Remove(distance.Key);
                    continue;
                }

                foreach (var index in distance.Value)
                {
                    SetTile(index, order, e.FrameCount);
                    order++;
                }
            }
        }
Beispiel #5
0
        void Draw()
        {
            Debug.Assert(Window.Exists);
            int width  = Window.Width;
            int height = Window.Height;

            CoreTrace.Log.Info("Engine", "Start draw");
            if (_windowResized)
            {
                _windowResized = false;

                GraphicsDevice.ResizeMainWindow((uint)width, (uint)height);
                Raise(new WindowResizedEvent(width, height));
                _sceneContext.RecreateWindowSizedResources(GraphicsDevice);
                CoreTrace.Log.Info("Engine", "Resize finished");
            }

            if (_newSampleCount != null)
            {
                _sceneContext.MainSceneSampleCount = _newSampleCount.Value;
                _newSampleCount = null;
                DestroyAllObjects();
                CreateAllObjects();
            }

            using (PerfTracker.FrameEvent("6.1 Render scenes"))
            {
                _frameCommands.Begin();

                var scenes = new List <Scene>();
                Raise(new CollectScenesEvent(scenes.Add));

                foreach (var scene in scenes)
                {
                    scene.RenderAllStages(GraphicsDevice, _frameCommands, _sceneContext, _renderers);
                }

                _frameCommands.End();
            }

            using (PerfTracker.FrameEvent("6.2 Submit commandlist"))
            {
                CoreTrace.Log.Info("Scene", "Submitting Commands");
                GraphicsDevice.SubmitCommands(_frameCommands);
                CoreTrace.Log.Info("Scene", "Submitted commands");
                GraphicsDevice.WaitForIdle();
            }
        }
Beispiel #6
0
        public Texture CreateDeviceTexture(GraphicsDevice gd, ResourceFactory rf, TextureUsage usage)
        {
            using var _ = PerfTracker.FrameEvent("6.1.2.1 Rebuild MultiTextures");
            if (IsMetadataDirty)
            {
                RebuildLayers();
            }

            var palette = PaletteManager.Palette.GetCompletePalette();

            using var staging = rf.CreateTexture(new TextureDescription(Width, Height, Depth, MipLevels, ArrayLayers, Format, TextureUsage.Staging, Type));
            staging.Name      = "T_" + Name + "_Staging";

            Span <uint> toBuffer = stackalloc uint[(int)(Width * Height)];

            foreach (var lsi in LogicalSubImages)
            {
                //if (!rebuildAll && !lsi.IsPaletteAnimated) // TODO: Requires caching a single Texture and then modifying it
                //    continue;

                for (int i = 0; i < lsi.Frames; i++)
                {
                    toBuffer.Fill(lsi.IsAlphaTested ? 0 : 0xff000000);
                    Rebuild(lsi, i, toBuffer, palette);

                    uint destinationLayer = (uint)LayerLookup[new LayerKey(lsi.Id, i)];

                    unsafe
                    {
                        fixed(uint *toBufferPtr = toBuffer)
                        {
                            gd.UpdateTexture(
                                staging, (IntPtr)toBufferPtr, Width * Height * sizeof(uint),
                                0, 0, 0,
                                Width, Height, 1,
                                0, destinationLayer);
                        }
                    }
                }
            }

            /* TODO: Mipmap
             *  for (uint level = 1; level < MipLevels; level++)
             *  {
             *  } //*/

            var texture = rf.CreateTexture(new TextureDescription(Width, Height, Depth, MipLevels, ArrayLayers, Format, usage, Type));

            texture.Name = "T_" + Name;

            using (CommandList cl = rf.CreateCommandList())
            {
                cl.Begin();
                cl.CopyTexture(staging, texture);
                cl.End();
                gd.SubmitCommands(cl);
            }

            IsDirty = false;
            return(texture);
        }
Beispiel #7
0
        public void Run()
        {
            ChangeBackend();
            PerfTracker.StartupEvent("Set up backend");
            Sdl2Native.SDL_Init(SDLInitFlags.GameController);
            ImGui.StyleColorsClassic();
            Raise(new WindowResizedEvent(Window.Width, Window.Height));
            Raise(new BeginFrameEvent());

            var frameCounter = new FrameCounter();

            PerfTracker.StartupEvent("Startup done, rendering first frame");
            while (!_done)
            {
                ChangeBackend();

                PerfTracker.BeginFrame();
                double deltaSeconds = frameCounter.StartFrame();
                using (PerfTracker.FrameEvent("1 Raising begin frame"))
                    Raise(new BeginFrameEvent());

                InputSnapshot snapshot;
                using (PerfTracker.FrameEvent("2 Processing SDL events"))
                {
                    Sdl2Events.ProcessEvents();
                    snapshot = Window.PumpEvents();
                }

                if (!Window.Exists)
                {
                    break;
                }

                if (_pendingCursorUpdate.HasValue)
                {
                    using (PerfTracker.FrameEvent("3 Warping mouse"))
                    {
                        Sdl2Native.SDL_WarpMouseInWindow(
                            Window.SdlWindowHandle,
                            (int)_pendingCursorUpdate.Value.X,
                            (int)_pendingCursorUpdate.Value.Y);

                        _pendingCursorUpdate = null;
                    }
                }

                using (PerfTracker.FrameEvent("4 Raising input event"))
                    Raise(new InputEvent(deltaSeconds, snapshot, Window.MouseDelta));

                using (PerfTracker.FrameEvent("5 Performing update"))
                    Update((float)deltaSeconds);

                if (!Window.Exists)
                {
                    break;
                }

                using (PerfTracker.FrameEvent("6 Drawing"))
                    Draw();

                var flags = Resolve <IEngineSettings>().Flags;
                if (GraphicsDevice.SyncToVerticalBlank != flags.HasFlag(EngineFlags.VSync))
                {
                    GraphicsDevice.SyncToVerticalBlank = flags.HasFlag(EngineFlags.VSync);
                }

                using (PerfTracker.FrameEvent("7 Swap buffers"))
                {
                    CoreTrace.Log.Info("Engine", "Swapping buffers...");
                    GraphicsDevice.SwapBuffers();
                    CoreTrace.Log.Info("Engine", "Draw complete");
                }
            }

            DestroyAllObjects();
            GraphicsDevice.Dispose();
            Window.Close();
        }
Beispiel #8
0
        public void RenderAllStages(GraphicsDevice gd, CommandList cl, SceneContext sc, IDictionary <Type, IRenderer> renderers)
        {
            sc.SetCurrentScene(this);

            // Collect all renderables from components
            foreach (var renderer in _renderables.Values)
            {
                renderer.Clear();
            }

            using (PerfTracker.FrameEvent("6.1.1 Collect renderables"))
            {
                Exchange.Raise(new RenderEvent(x =>
                {
                    if (x == null || !_activeRendererTypes.Contains(x.Renderer))
                    {
                        return;
                    }
                    if (!_renderables.ContainsKey(x.Renderer))
                    {
                        _renderables[x.Renderer] = new List <IRenderable>();
                    }
                    _renderables[x.Renderer].Add(x);
                }), this);
            }

            foreach (var renderer in _renderables)
            {
                CoreTrace.Log.CollectedRenderables(renderer.Key.Name, 0, renderer.Value.Count);
            }

            var newPalette = Resolve <IPaletteManager>().PaletteTexture;

            if (sc.PaletteView == null || _paletteTexture != newPalette)
            {
                sc.PaletteView?.Dispose();
                sc.PaletteTexture?.Dispose();
                CoreTrace.Log.Info("Scene", "Disposed palette device texture");
                _paletteTexture   = newPalette;
                sc.PaletteTexture = _paletteTexture.CreateDeviceTexture(gd, gd.ResourceFactory, TextureUsage.Sampled);
                sc.PaletteView    = gd.ResourceFactory.CreateTextureView(sc.PaletteTexture);
            }
            CoreTrace.Log.Info("Scene", "Created palette device texture");

            using (PerfTracker.FrameEvent("6.1.2 Prepare per-frame resources"))
                using (new RenderDebugGroup(cl, "Prepare per-frame resources"))
                {
                    _processedRenderables.Clear();
                    foreach (var renderableGroup in _renderables)
                    {
                        var renderer = renderers[renderableGroup.Key];
                        foreach (var renderable in renderer.UpdatePerFrameResources(gd, cl, sc,
                                                                                    renderableGroup.Value))
                        {
                            if (!_processedRenderables.ContainsKey(renderable.RenderOrder))
                            {
                                _processedRenderables[renderable.RenderOrder] = new List <IRenderable>();
                            }
                            _processedRenderables[renderable.RenderOrder].Add(renderable);
                        }
                    }

                    CoreTrace.Log.CollectedRenderables("ProcessedRenderables",
                                                       _processedRenderables.Count,
                                                       _processedRenderables.Sum(x => x.Value.Count));
                }

            var orderedKeys = _processedRenderables.Keys.OrderBy(x => x).ToList();

            CoreTrace.Log.Info("Scene", "Sorted processed renderables");
            float depthClear = gd.IsDepthRangeZeroToOne ? 1f : 0f;

            // Main scene
            using (PerfTracker.FrameEvent("6.1.3 Main scene pass"))
                using (new RenderDebugGroup(cl, "Main Scene Pass"))
                {
                    sc.UpdateCameraBuffers(cl);
                    cl.SetFramebuffer(sc.MainSceneFramebuffer);
                    var fbWidth  = sc.MainSceneFramebuffer.Width;
                    var fbHeight = sc.MainSceneFramebuffer.Height;
                    cl.SetViewport(0, new Viewport(0, 0, fbWidth, fbHeight, 0, 1));
                    cl.SetFullViewports();
                    cl.SetFullScissorRects();
                    cl.ClearColorTarget(0, _clearColour);
                    cl.ClearDepthStencil(depthClear);
                    foreach (var key in orderedKeys)
                    {
                        Render(gd, cl, sc, RenderPasses.Standard, renderers, _processedRenderables[key]);
                    }
                }

            // 2D Overlays
            using (new RenderDebugGroup(cl, "Overlay"))
            {
                foreach (var key in orderedKeys)
                {
                    Render(gd, cl, sc, RenderPasses.Overlay, renderers, _processedRenderables[key]);
                }
            }

            if (sc.MainSceneColorTexture.SampleCount != TextureSampleCount.Count1)
            {
                cl.ResolveTexture(sc.MainSceneColorTexture, sc.MainSceneResolvedColorTexture);
            }

            using (new RenderDebugGroup(cl, "Duplicator"))
            {
                cl.SetFramebuffer(sc.DuplicatorFramebuffer);
                cl.SetFullViewports();
                foreach (var key in orderedKeys)
                {
                    Render(gd, cl, sc, RenderPasses.Duplicator, renderers, _processedRenderables[key]);
                }
            }

            using (new RenderDebugGroup(cl, "Swapchain Pass"))
            {
                cl.SetFramebuffer(gd.SwapchainFramebuffer);
                cl.SetFullViewports();
                foreach (var key in orderedKeys)
                {
                    Render(gd, cl, sc, RenderPasses.SwapchainOutput, renderers, _processedRenderables[key]);
                }
            }
        }