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)); } }
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); } } }
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(); }
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++; } } }
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(); } }
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); }
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(); }
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]); } } }