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
@@ -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);