Separate GraphicsContext from Window, prepare for windows and swap chain for multi window

This commit is contained in:
Simon Lübeß
2024-09-10 19:07:58 +02:00
parent 65992126c0
commit 352073869f
16 changed files with 99 additions and 130 deletions
+4 -4
View File
@@ -118,7 +118,7 @@ namespace GlitchyEditor
[AllowAppend]
public this(String[] args, EditorContentManager contentManager) : base("Editor")
{
Application.Get().Window.IsVSync = true;
Application.Get().MainWindow.IsVSync = true;
ScriptEngine.ApplicationInfo.IsEditor = true;
@@ -306,7 +306,7 @@ namespace GlitchyEditor
private void InitGraphics()
{
_context = Application.Get().Window.Context..AddRef();
_context = Application.Instance.ImmediateContext..AddRef();
RasterizerStateDescription rsDesc = .(.Solid, .Back, true);
_rasterizerState = new RasterizerState(rsDesc);
@@ -471,7 +471,7 @@ namespace GlitchyEditor
RenderCommand.SetRenderTarget(null, 0, true);
RenderCommand.BindRenderTargets();
RenderCommand.SetViewport(_context.SwapChain.BackbufferViewport);
RenderCommand.SetViewport(Application.Instance.MainWindow.SwapChain.BackbufferViewport);
}
private void DebugDraw3D()
@@ -583,7 +583,7 @@ namespace GlitchyEditor
title.AppendF($" | {_editorScene.Name}");
}
Application.Instance.Window.Title = title;
Application.Instance.MainWindow.Title = title;
}
#region Project Management
+20 -8
View File
@@ -14,7 +14,7 @@ namespace GlitchyEngine
{
static Application s_Instance = null;
private Window _window;
private Window _mainWindow;
private RendererAPI _rendererApi;
private bool _running = true;
@@ -25,6 +25,10 @@ namespace GlitchyEngine
#if IMGUI
private ImGuiLayer _imGuiLayer;
#endif
private GraphicsContext _immediateGraphicsContext ~ _?.ReleaseRef();
public GraphicsContext ImmediateContext => _immediateGraphicsContext;
private GameTime _gameTime;
@@ -34,7 +38,7 @@ namespace GlitchyEngine
private append Monitor _jobQueueMutex = .();
public bool IsRunning => _running;
public Window Window => _window;
public Window MainWindow => _mainWindow;
public IContentManager ContentManager => _contentManager;
@@ -61,9 +65,17 @@ namespace GlitchyEngine
WindowDescription windowDesc = .Default;
windowDesc.Icon = "Resources/Textures/GlitchyEngineIcon.ico";
if (GraphicsContext.Get() == null)
{
_immediateGraphicsContext = new GraphicsContext(null, true);
_immediateGraphicsContext.Init();
}
_window = new Window(windowDesc);
_window.EventCallback = new => OnEvent;
_mainWindow = new Window(windowDesc);
_mainWindow.EventCallback = new => OnEvent;
_immediateGraphicsContext.CurrentWindow = _mainWindow;
Input.Init();
@@ -71,7 +83,7 @@ namespace GlitchyEngine
// TODO: RenderAPI in RenderCommand initialisieren?
_rendererApi = new RendererAPI();
_rendererApi.Context = _window.Context;
_rendererApi.Context = _immediateGraphicsContext;
SamplerStateManager.Init();
@@ -110,7 +122,7 @@ namespace GlitchyEngine
delete _layerStack;
delete _rendererApi;
delete _window;
delete _mainWindow;
delete _gameTime;
@@ -178,7 +190,7 @@ namespace GlitchyEngine
layer.Update(_gameTime);
}
_window.Update();
_mainWindow.Update();
if(allowFrame)
{
@@ -186,7 +198,7 @@ namespace GlitchyEngine
_imGuiLayer.ImGuiRender();
#endif
_window.Context.SwapChain.Present();
_mainWindow.SwapChain.Present();
}
}
}
+1 -1
View File
@@ -54,7 +54,7 @@ namespace GlitchyEngine.ImGui
}
#if BF_PLATFORM_WINDOWS
ImGuiImplWin32.Init(Application.Get().Window.NativeWindow);
ImGuiImplWin32.Init(Application.Instance.MainWindow.NativeWindow);
#endif
#if GE_GRAPHICS_DX11
@@ -38,8 +38,9 @@ namespace GlitchyEngine
public void Update(GameTime gameTime)
{
Debug.Profiler.ProfileFunction!();
if(Application.Get().Window.IsActive)
// TODO: Don't check the main window instead check the editor view window
if(Application.Instance.MainWindow.IsActive)
{
float3 movement = .();
@@ -98,7 +98,8 @@ namespace GlitchyEngine
{
Debug.Profiler.ProfileFunction!();
if(Application.Get().Window.IsActive)
// TODO: Don't check the main window instead check the editor view window
if(Application.Instance.MainWindow.IsActive)
{
float3 movement = .();
@@ -19,10 +19,6 @@ namespace GlitchyEngine.Renderer
/// DirectX 11 specific implementation of the GraphicsContext
extension GraphicsContext
{
private SwapChain _swapChain;
internal Windows.HWnd nativeWindowHandle;
/// Gets whether or not the DX11 device is initialized.
//internal bool IsDx11Initialized => nativeDevice != null;
//internal ID3D11Device* nativeDevice => NativeDevice;
@@ -30,7 +26,7 @@ namespace GlitchyEngine.Renderer
//internal ID3D11Debug* debugDevice => DebugDevice;
public override SwapChain SwapChain => _swapChain;
//public override SwapChain SwapChain => _mainWindow.SwapChain;
private const uint32 MaxRTVCount = DirectX.D3D11.D3D11_SIMULTANEOUS_RENDER_TARGET_COUNT;
@@ -41,23 +37,10 @@ namespace GlitchyEngine.Renderer
//public static override uint32 MaxRenderTargetCount() => MaxRTVCount;
public this(Windows.HWnd windowHandle)
{
Debug.Profiler.ProfileFunction!();
nativeWindowHandle = windowHandle;
_swapChain = new SwapChain(this);
s_GraphicsContext = this;
}
public ~this()
{
Debug.Profiler.ProfileFunction!();
delete _swapChain;
Dx11Release();
}
@@ -65,57 +48,12 @@ namespace GlitchyEngine.Renderer
{
Debug.Profiler.ProfileFunction!();
Dx11Init();
SwapChain.Init();
}
/**
* Initializes the Device and ImmediateContext.
*/
/*
void InitDevice()
{
if(!IsDx11Initialized)
if (_immediateContext)
{
Log.EngineLogger.Trace("Creating D3D11 Device and Context...");
DeviceCreationFlags deviceFlags = .None;
#if DEBUG
deviceFlags |= .Debug;
#endif
FeatureLevel[] levels = scope .(.Level_11_0);
FeatureLevel deviceLevel = ?;
var deviceResult = D3D11.CreateDevice(null, .Hardware, 0, deviceFlags, levels, &nativeDevice, &deviceLevel, &nativeContext);
Log.EngineLogger.Assert(deviceResult.Succeeded, scope $"Failed to create D3D11 Device. Message({(int32)deviceResult}): {deviceResult}");
#if DEBUG
if(nativeDevice.QueryInterface<ID3D11Debug>(out debugDevice).Succeeded)
{
ID3D11InfoQueue* infoQueue;
if(nativeDevice.QueryInterface<ID3D11InfoQueue>(out infoQueue).Succeeded)
{
infoQueue.SetBreakOnSeverity(.Corruption, true);
infoQueue.SetBreakOnSeverity(.Error, true);
infoQueue.Release();
}
}
#endif
Log.EngineLogger.Trace($"D3D11 Device and Context created (Feature level: {deviceLevel})");
}
else
{
// We created a second GraphicsContext (for some reason?) just increment references.
nativeDevice.AddRef();
nativeContext.AddRef();
debugDevice.AddRef();
s_GraphicsContext = this;
Dx11Init();
}
}
*/
private ID3D11DepthStencilView* _depthStencilTarget;
private ID3D11RenderTargetView*[MaxRTVCount] _renderTargets;
@@ -132,11 +70,11 @@ namespace GlitchyEngine.Renderer
public override void SetRenderTarget(RenderTarget2D renderTarget, int slot, bool setDepthTarget)
{
_renderTargets[slot] = (renderTarget ?? _swapChain.BackBuffer)._nativeRenderTargetView;
_renderTargets[slot] = (renderTarget ?? _currentWindow.SwapChain.BackBuffer)._nativeRenderTargetView;
if(slot == 0 && setDepthTarget)
{
SetDepthStencilTarget((renderTarget ?? _swapChain.BackBuffer).DepthStencilTarget);
SetDepthStencilTarget((renderTarget ?? _currentWindow.SwapChain.BackBuffer).DepthStencilTarget);
}
}
@@ -168,7 +106,7 @@ namespace GlitchyEngine.Renderer
{
using (ContextMonitor.Enter())
{
NativeContext.ClearRenderTargetView((renderTarget ?? _swapChain.BackBuffer)._nativeRenderTargetView, color);
NativeContext.ClearRenderTargetView((renderTarget ?? _currentWindow.SwapChain.BackBuffer)._nativeRenderTargetView, color);
}
}
@@ -47,14 +47,12 @@ namespace GlitchyEngine.Renderer
ReleaseAndNullify();
if(_description.IsSwapchainTarget)
if(_description.SwapChain != null)
{
// TODO: if the engine supports multiple windows it has to support multiple swap chains.
// kinda dirty...
var context = GraphicsContext.Get();
context.SwapChain.GetBackbuffer(out _nativeTexture);
// Still dirty, we need to be able to pass in which swap chain to use!
_description.SwapChain.GetBackbuffer(out _nativeTexture);
CreateViews();
}
@@ -99,8 +97,9 @@ namespace GlitchyEngine.Renderer
private void CreateViews()
{
Debug.Profiler.ProfileResourceFunction!();
if(_description.IsSwapchainTarget)
// TODO: Why did we branch here?
/*if(_description.Swapchain != null)
{
var result = NativeDevice.CreateShaderResourceView(_nativeTexture, null, &_nativeResourceView);
Log.EngineLogger.Assert(result.Succeeded, "Failed to create resource view");
@@ -111,7 +110,7 @@ namespace GlitchyEngine.Renderer
result = NativeDevice.CreateRenderTargetView(_nativeTexture, null, &_nativeRenderTargetView);
Log.EngineLogger.Assert(result.Succeeded, "Failed to create render target view");
}
else
else*/
{
var result = NativeDevice.CreateShaderResourceView(_nativeTexture, null, &_nativeResourceView);
Log.EngineLogger.Assert(result.Succeeded, "Failed to create resource view");
@@ -372,11 +371,9 @@ namespace GlitchyEngine.Renderer
if (target.IsSwapchainTarget)
{
// TODO: if the engine supports multiple windows it has to support multiple swap chains.
// kinda dirty...
var context = GraphicsContext.Get();
context.SwapChain.GetBackbuffer(out _nativeTextures[i]);
// Still dirty, we need to be able to pass in which swap chain to use!
Application.Instance.MainWindow.SwapChain.GetBackbuffer(out _nativeTextures[i]);
}
else
{
@@ -39,7 +39,7 @@ namespace GlitchyEngine.Renderer
private mixin RtOrBackbuffer(RenderTarget2D renderTarget)
{
renderTarget ?? _context.SwapChain.BackBuffer
renderTarget ?? _context.CurrentWindow.SwapChain.BackBuffer
}
public override void Clear(RenderTarget2D renderTarget, ColorRGBA color)
@@ -10,6 +10,8 @@ using internal GlitchyEngine.Platform.DX11;
namespace GlitchyEngine.Renderer
{
using internal GlitchyEngine;
public extension SwapChain
{
internal DirectX.DXGI.IDXGIDevice* nativeDxgiDevice;
@@ -34,7 +36,7 @@ namespace GlitchyEngine.Renderer
void SetResolutionFromWindow()
{
DirectX.Windows.Winuser.GetClientRect(_context.nativeWindowHandle, let rect);
DirectX.Windows.Winuser.GetClientRect(_window._windowHandle, let rect);
Width = (.)(rect.Right - rect.Left);
Height = (.)(rect.Bottom - rect.Top);
@@ -68,7 +70,7 @@ namespace GlitchyEngine.Renderer
uint32 backBufferCount = 2;
Format backBufferFormat = .R8G8B8A8_UNorm;
Format backBufferViewFormat = .R8G8B8A8_UNorm; // _SRGB
// TODO: Allow this: Format backBufferViewFormat = .R8G8B8A8_UNorm_SRGB;
if(nativeSwapChain != null)
{
@@ -101,7 +103,7 @@ namespace GlitchyEngine.Renderer
SwapChainFullscreenDescription fsSwapChainDesc = .();
fsSwapChainDesc.Windowed = true;
var createResult = factory.CreateSwapChainForHwnd((.)NativeDevice, _context.nativeWindowHandle, ref swDesc, &fsSwapChainDesc, null, &nativeSwapChain);
var createResult = factory.CreateSwapChainForHwnd((.)NativeDevice, _window._windowHandle, ref swDesc, &fsSwapChainDesc, null, &nativeSwapChain);
if(createResult.Failed)
{
Log.EngineLogger.Error($"Failed to create swap chain. Message({(int)createResult}):{createResult}");
@@ -112,7 +114,7 @@ namespace GlitchyEngine.Renderer
RenderTarget2DDescription desc = .(backBufferFormat, _width, _height);
desc.DepthStencilFormat = _depthStencilFormat;
desc.IsSwapchainTarget = true;
desc.SwapChain = this;
// Todo: perhaps just update the render target
_backBuffer = new RenderTarget2D(desc);
@@ -132,7 +134,7 @@ namespace GlitchyEngine.Renderer
{
Debug.Profiler.ProfileFunction!();
nativeSwapChain.Present(Application.Get().Window.IsVSync ? 1 : 0, .None);
nativeSwapChain.Present(_window.IsVSync ? 1 : 0, .None);
}
}
}
@@ -194,7 +194,7 @@ namespace GlitchyEngine
public override static void SetMousePosition(int2 pos)
{
HWnd windowHandle = (HWnd)(int)Application.Get().Window.NativeWindow;
HWnd windowHandle = (HWnd)(int)Application.Get().MainWindow.NativeWindow;
var pos;
@@ -213,7 +213,7 @@ namespace GlitchyEngine
public override static void Impl_NewFrame()
{
Window window = Application.Get().Window;
Window window = Application.Get().MainWindow;
Debug.Profiler.ProfileFunction!();
@@ -260,7 +260,7 @@ namespace GlitchyEngine
public override static void Impl_EndFrame()
{
Application.Get().Window.[Friend]_rawMouseMovementAccumulator = .Zero;
Application.Get().MainWindow.[Friend]_rawMouseMovementAccumulator = .Zero;
}
}
}
@@ -23,7 +23,7 @@ namespace GlitchyEngine
const String WindowClassName = "GlitchyEngineWindow";
private Windows.HInstance _instanceHandle;
private Windows.HWnd _windowHandle;
internal Windows.HWnd _windowHandle;
private WindowClassExW _windowClass;
@@ -37,10 +37,6 @@ namespace GlitchyEngine
private bool _isActive;
private GraphicsContext _graphicsContext ~ _?.ReleaseRef();
public override GraphicsContext Context => _graphicsContext;
public override int32 MinWidth
{
get => _minMaxInfo.MinimumTrackingSize.x;
@@ -230,9 +226,9 @@ namespace GlitchyEngine
_windowHandle = CreateWindowExW(.None, _windowClass.ClassName, desc.Title.ToScopedNativeWChar!(), .WS_OVERLAPPEDWINDOW | .WS_VISIBLE,
CW_USEDEFAULT, CW_USEDEFAULT, desc.Width, desc.Height, 0, 0, (.)_instanceHandle, null);
}
_graphicsContext = new GraphicsContext(_windowHandle);
_graphicsContext.Init();
_swapChain = new SwapChain(this);
_swapChain.Init();
void* myPtr = Internal.UnsafeCastToPtr(this);
SetWindowLongPtrW(_windowHandle, GWL_USERDATA, (int)myPtr);
@@ -300,10 +296,10 @@ namespace GlitchyEngine
if(window._clientRect.Width != 0 && window._clientRect.Height != 0)
{
window._graphicsContext.SwapChain.Width = (.)window._clientRect.Width;
window._graphicsContext.SwapChain.Height = (.)window._clientRect.Height;
window._swapChain.Width = (.)window._clientRect.Width;
window._swapChain.Height = (.)window._clientRect.Height;
window._graphicsContext.SwapChain.ApplyChanges();
window._swapChain.ApplyChanges();
}
WindowResizeEvent event = scope WindowResizeEvent(window._clientRect.Width, window._clientRect.Height, window._isResizingOrMoving);
+15 -1
View File
@@ -8,11 +8,25 @@ namespace GlitchyEngine.Renderer
{
private static GraphicsContext s_GraphicsContext;
public static GraphicsContext Get() => s_GraphicsContext;
private Window _currentWindow;
public extern SwapChain SwapChain {get;}
private bool _immediateContext;
public Window CurrentWindow
{
get => _currentWindow;
set => _currentWindow = value;
}
protected extern void PlatformConstruct();
public this(Window currentWindow, bool immediateContext = false)
{
_currentWindow = currentWindow;
_immediateContext = immediateContext;
}
/**
* The maximum number of simultaneous rendertargets supported.
*/
+4 -3
View File
@@ -17,10 +17,11 @@ namespace GlitchyEngine.Renderer
public uint32 SampleCount;
public uint32 SampleQuality;
public DepthStencilFormat DepthStencilFormat;
public bool IsSwapchainTarget;
/// If not null, the render target will represent the specified swap chains back buffer.
public SwapChain SwapChain;
public this(Format pixelFormat, uint32 width, uint32 height, uint32 arraySize = 1, uint32 mipLevels = 1,
DepthStencilFormat depthStencilFormat = .Unknown, CPUAccessFlags cpuAccess = .None, uint32 sampleCount = 1, uint32 sampleQuality = 0, bool isSwapchainTarget = false)
DepthStencilFormat depthStencilFormat = .Unknown, CPUAccessFlags cpuAccess = .None, uint32 sampleCount = 1, uint32 sampleQuality = 0, SwapChain swapChain = null)
{
PixelFormat = pixelFormat;
Width = width;
@@ -33,7 +34,7 @@ namespace GlitchyEngine.Renderer
SampleCount = sampleCount;
SampleQuality = sampleQuality;
IsSwapchainTarget = isSwapchainTarget;
SwapChain = swapChain;
}
}
+1 -1
View File
@@ -28,7 +28,7 @@ namespace GlitchyEngine.Renderer
{
Debug.Profiler.ProfileRendererFunction!();
var actualRt = (renderTarget ?? GraphicsContext.Get().SwapChain.BackBuffer);
var actualRt = (renderTarget ?? GraphicsContext.Get().CurrentWindow.SwapChain.BackBuffer);
if(options.HasFlag(.Color))
Clear(actualRt, color);
+9 -1
View File
@@ -3,8 +3,9 @@ namespace GlitchyEngine.Renderer
public class SwapChain
{
private GraphicsContext _context;
private Window _window;
private bool _changed;
private bool _changed = true;
private uint32 _width, _height;
@@ -16,6 +17,8 @@ namespace GlitchyEngine.Renderer
public GraphicsContext Context => _context;
public Window Window => _window;
/**
* Gets or Sets the backbuffers width.
* @remarks @ApplyChanges() needs to be called in order to apply the changes.
@@ -77,6 +80,11 @@ namespace GlitchyEngine.Renderer
public RenderTarget2D BackBuffer => _backBuffer;
public this(Window window)
{
_window = window;
}
public extern void Init();
/**
+5 -6
View File
@@ -27,10 +27,14 @@ namespace GlitchyEngine
public class Window
{
private SwapChain _swapChain ~ delete _;
public delegate void EventCallback(Event e);
protected EventCallback _eventCallback ~ delete _;
public SwapChain SwapChain => _swapChain;
public extern this(WindowDescription windowDescription);
/**
@@ -87,11 +91,6 @@ namespace GlitchyEngine
* Gets or Sets whether or not the application uses VSync
*/
public extern bool IsVSync {get; set;}
/**
* Gets the windows graphics context.
*/
public extern GraphicsContext Context {get;}
/**
* Gets a pointer to the platform specific window representation.