diff --git a/GlitchyEngine/src/ImGui/ImGuiExtension.bf b/GlitchyEngine/src/ImGui/ImGuiExtension.bf index ec01860..2b73b3d 100644 --- a/GlitchyEngine/src/ImGui/ImGuiExtension.bf +++ b/GlitchyEngine/src/ImGui/ImGuiExtension.bf @@ -18,5 +18,7 @@ namespace ImGui public static bool ColorPicker4(char* label, ref ColorRGBA col, ColorEditFlags flags = (ColorEditFlags) 0, float* ref_col = null) => ColorPicker4Impl(label, *(float[4]*)&col, flags, ref_col); public static extern void Image(Texture2D texture, Vec2 size, Vec2 uv0 = Vec2.Zero, Vec2 uv1 = Vec2.Ones, Vec4 tint_col = Vec4.Ones, Vec4 border_col = Vec4.Zero); + // Wouldn't be necesseary if RenderTarget2D was Texture2D + public static extern void Image(RenderTarget2D texture, Vec2 size, Vec2 uv0 = Vec2.Zero, Vec2 uv1 = Vec2.Ones, Vec4 tint_col = Vec4.Ones, Vec4 border_col = Vec4.Zero); } } diff --git a/GlitchyEngine/src/Platform/DX11/ImGui/ImGui.bf b/GlitchyEngine/src/Platform/DX11/ImGui/ImGui.bf index 4737035..9946010 100644 --- a/GlitchyEngine/src/Platform/DX11/ImGui/ImGui.bf +++ b/GlitchyEngine/src/Platform/DX11/ImGui/ImGui.bf @@ -10,5 +10,10 @@ namespace ImGui { ImGui.Image(texture.nativeResourceView, size, uv0, uv1, tint_col, border_col); } + + public static override void Image(RenderTarget2D texture, Vec2 size, Vec2 uv0 = Vec2.Zero, Vec2 uv1 = Vec2.Ones, Vec4 tint_col = Vec4.Ones, Vec4 border_col = Vec4.Zero) + { + ImGui.Image(texture._nativeResourceView, size, uv0, uv1, tint_col, border_col); + } } } diff --git a/GlitchyEngine/src/Platform/DX11/Renderer/Dx11DepthStencilTarget.bf b/GlitchyEngine/src/Platform/DX11/Renderer/Dx11DepthStencilTarget.bf index ea25cc3..a3834c3 100644 --- a/GlitchyEngine/src/Platform/DX11/Renderer/Dx11DepthStencilTarget.bf +++ b/GlitchyEngine/src/Platform/DX11/Renderer/Dx11DepthStencilTarget.bf @@ -17,10 +17,14 @@ namespace GlitchyEngine.Renderer return .D32_Float; case .D32_Float_S8X24_UInt: return .D32_Float_S8X24_UInt; + case .None: + Log.EngineLogger.Assert(false, "None is not a valid depth stencil format"); + return .Unknown; } } } + // TODO: Depth stencil target is technically just a RenderTarget extension DepthStencilTarget { internal ID3D11DepthStencilView* nativeView ~ _?.Release(); diff --git a/GlitchyEngine/src/Platform/DX11/Renderer/Dx11GraphicsContext.bf b/GlitchyEngine/src/Platform/DX11/Renderer/Dx11GraphicsContext.bf index cb73c2d..064dd53 100644 --- a/GlitchyEngine/src/Platform/DX11/Renderer/Dx11GraphicsContext.bf +++ b/GlitchyEngine/src/Platform/DX11/Renderer/Dx11GraphicsContext.bf @@ -104,13 +104,18 @@ namespace GlitchyEngine.Renderer public override void SetRenderTarget(RenderTarget2D renderTarget, int slot = 0) { - if(renderTarget == null) + if(renderTarget == null || renderTarget.Description.IsSwapchainTarget) { _renderTargets[slot] = _swapChain.nativeBackBufferTarget; } else { - _renderTargets[slot] = renderTarget.nativeRenderTargetView; + _renderTargets[slot] = renderTarget._nativeRenderTargetView; + } + + if(slot == 0) + { + SetDepthStencilTarget(renderTarget?.DepthStencilTarget); } } @@ -127,7 +132,7 @@ namespace GlitchyEngine.Renderer } else { - nativeContext.ClearRenderTargetView(renderTarget.nativeRenderTargetView, color); + nativeContext.ClearRenderTargetView(renderTarget._nativeRenderTargetView, color); } } diff --git a/GlitchyEngine/src/Platform/DX11/Renderer/Dx11RenderTarget.bf b/GlitchyEngine/src/Platform/DX11/Renderer/Dx11RenderTarget.bf index 5c4c69a..bcb169c 100644 --- a/GlitchyEngine/src/Platform/DX11/Renderer/Dx11RenderTarget.bf +++ b/GlitchyEngine/src/Platform/DX11/Renderer/Dx11RenderTarget.bf @@ -1,3 +1,4 @@ +using DirectX.Common; using DirectX.D3D11; namespace GlitchyEngine.Renderer @@ -6,17 +7,73 @@ namespace GlitchyEngine.Renderer extension RenderTarget2D { - protected internal ID3D11RenderTargetView* nativeRenderTargetView ~ _?.Release(); + protected internal ID3D11Texture2D* _nativeTexture ~ _?.Release(); + protected internal ID3D11ShaderResourceView* _nativeResourceView ~ _?.Release(); + protected internal ID3D11RenderTargetView* _nativeRenderTargetView ~ _?.Release(); - protected override void CreateRenderTargetPlatform(Texture2DDesc desc) + private void ReleaseAndNullify() { - nativeRenderTargetView?.Release(); - nativeRenderTargetView = null; + ReleaseAndNullify!(_nativeTexture); + ReleaseAndNullify!(_nativeResourceView); + ReleaseAndNullify!(_nativeRenderTargetView); - CreateTexturePlatform(desc, true, null, 0); + ReleaseRefAndNullify!(_depthStenilTarget); + } - var result = _context.nativeDevice.CreateRenderTargetView(nativeTexture, null, &nativeRenderTargetView); - Log.EngineLogger.Assert(result.Succeeded, scope $"Failed to create render target view. Error ({result.Underlying}): {result}"); + public override void Resize(uint32 width, uint32 height) + { + ReleaseAndNullify(); + + _description.Width = width; + _description.Height = height; + + ApplyChanges(); + } + + protected override void PlatformApplyChanges() + { + ReleaseAndNullify(); + + PlatformCreateTexture(); + + if(_description.DepthStencilFormat != .None) + { + _depthStenilTarget = new DepthStencilTarget(_context, _description.Width, _description.Height, _description.DepthStencilFormat); + } + } + + private void PlatformCreateTexture() + { + Texture2DDescription desc = .() + { + Width = _description.Width, + Height = _description.Height, + ArraySize = _description.ArraySize, + MipLevels = _description.MipLevels, + Format = _description.PixelFormat, + // Always bindable as ShaderResource and RenderTarget + BindFlags = .ShaderResource | .RenderTarget, + CpuAccessFlags = (.)_description.CpuAccess, + // 2D RenderTarget never has misc flags + MiscFlags = .None, + SampleDesc = .(_description.SampleCount, _description.SampleQuality), + // RenderTarget has always Default usage + Usage = .Default + }; + + var result = _context.nativeDevice.CreateTexture2D(ref desc, null, &_nativeTexture); + Log.EngineLogger.Assert(result.Succeeded, "Failed to create RenderTarget2D"); + + CreateViews(); + } + + private void CreateViews() + { + var result = _context.nativeDevice.CreateShaderResourceView(_nativeTexture, null, &_nativeResourceView); + Log.EngineLogger.Assert(result.Succeeded, "Failed to create resource view"); + + result = _context.nativeDevice.CreateRenderTargetView(_nativeTexture, null, &_nativeRenderTargetView); + Log.EngineLogger.Assert(result.Succeeded, "Failed to create render target view"); } } } diff --git a/GlitchyEngine/src/Platform/DX11/Renderer/Dx11RendererAPI.bf b/GlitchyEngine/src/Platform/DX11/Renderer/Dx11RendererAPI.bf index ec8bcde..f70ca6a 100644 --- a/GlitchyEngine/src/Platform/DX11/Renderer/Dx11RendererAPI.bf +++ b/GlitchyEngine/src/Platform/DX11/Renderer/Dx11RendererAPI.bf @@ -32,6 +32,11 @@ namespace GlitchyEngine.Renderer { _context.nativeContext.ClearDepthStencilView(target.nativeView, (.)clearFlags, depthValue, stencilValue); } + + public override void Clear(RenderTarget2D renderTarget, float depthValue, uint8 stencilValue, DepthStencilClearFlag clearFlags) + { + _context.nativeContext.ClearDepthStencilView(renderTarget._depthStenilTarget.nativeView, (.)clearFlags, depthValue, stencilValue); + } public override void DrawIndexed(GeometryBinding geometry) { diff --git a/GlitchyEngine/src/Renderer/DepthStencilTarget.bf b/GlitchyEngine/src/Renderer/DepthStencilTarget.bf index c28d264..eb49f01 100644 --- a/GlitchyEngine/src/Renderer/DepthStencilTarget.bf +++ b/GlitchyEngine/src/Renderer/DepthStencilTarget.bf @@ -6,7 +6,8 @@ namespace GlitchyEngine.Renderer D16_UNorm, D24_UNorm_S8_UInt, D32_Float, - D32_Float_S8X24_UInt + D32_Float_S8X24_UInt, + None } // TODO: add all features. @@ -23,6 +24,8 @@ namespace GlitchyEngine.Renderer public this(GraphicsContext context, uint32 width, uint32 height, DepthStencilFormat format = .D32_Float) { + Log.EngineLogger.Assert(format != .None, "DepthStencilFormat None is only valid for RenderTarget"); + _context = context..AddRef(); _width = width; _height = height; diff --git a/GlitchyEngine/src/Renderer/GraphicsContext.bf b/GlitchyEngine/src/Renderer/GraphicsContext.bf index bc8492d..110b7c9 100644 --- a/GlitchyEngine/src/Renderer/GraphicsContext.bf +++ b/GlitchyEngine/src/Renderer/GraphicsContext.bf @@ -16,12 +16,10 @@ namespace GlitchyEngine.Renderer public extern void Init(); - /** - * Sets a rendertarget. - * @param renderTarget The render target. - * @param slot The slot to which the rendertarget will be bound. - * @remarks When @RenderTarget is null the backbuffer will be bound. - * @BindRenderTargets has to be called in order to bind the rendertargets. + /** @brief Sets a rendertarget to the given slot. + * @BindRenderTargets has to be called in order to bind the rendertargets. + * @param renderTarget The render target to set. If null, the backbuffer will be set. + * @param slot The slot to which the rendertarget will be bound. If 0 the depth buffer of the current render target will be set. If it has no depthbuffer the current will be unset. */ public extern void SetRenderTarget(RenderTarget2D renderTarget, int slot = 0); diff --git a/GlitchyEngine/src/Renderer/RenderCommand.bf b/GlitchyEngine/src/Renderer/RenderCommand.bf index af13b7c..7c52e23 100644 --- a/GlitchyEngine/src/Renderer/RenderCommand.bf +++ b/GlitchyEngine/src/Renderer/RenderCommand.bf @@ -9,7 +9,7 @@ namespace GlitchyEngine.Renderer Depth = 1, Stencil = 2 } - + public static class RenderCommand { private static RendererAPI _rendererAPI; @@ -31,12 +31,15 @@ namespace GlitchyEngine.Renderer { _rendererAPI.Clear(renderTarget, color); } - - [Inline] - public static void Clear(DepthStencilTarget target, float depthValue, uint8 stencilValue, DepthStencilClearFlag clearFlags) + public static void Clear(DepthStencilTarget depthTarget, float depthValue, uint8 stencilValue, DepthStencilClearFlag clearFlags) { - _rendererAPI.Clear(target, depthValue, stencilValue, clearFlags); + _rendererAPI.Clear(depthTarget, depthValue, stencilValue, clearFlags); + } + + public static void Clear(RenderTarget2D renderTarget, float depthValue, uint8 stencilValue, DepthStencilClearFlag clearFlags) + { + _rendererAPI.Clear(renderTarget, depthValue, stencilValue, clearFlags); } [Inline] diff --git a/GlitchyEngine/src/Renderer/RenderTarget.bf b/GlitchyEngine/src/Renderer/RenderTarget.bf index afc40d1..c4af0e6 100644 --- a/GlitchyEngine/src/Renderer/RenderTarget.bf +++ b/GlitchyEngine/src/Renderer/RenderTarget.bf @@ -1,25 +1,83 @@ using System; namespace GlitchyEngine.Renderer { - public class RenderTarget2D : Texture2D + public struct RenderTarget2DDescription { - public this(GraphicsContext context, uint32 width, uint32 height, Format format, uint32 arraySize = 1, uint32 mipLevels = 1, CPUAccessFlags cpuAccess = .None) - : base(context) + public uint32 Width; + public uint32 Height; + public uint32 ArraySize; + public uint32 MipLevels; + public Format PixelFormat; + public CPUAccessFlags CpuAccess; + public uint32 SampleCount; + public uint32 SampleQuality; + public DepthStencilFormat DepthStencilFormat; + public bool IsSwapchainTarget; + + public this(Format pixelFormat, uint32 width, uint32 height, uint32 arraySize = 1, uint32 mipLevels = 1, + DepthStencilFormat depthStencilFormat = .None, CPUAccessFlags cpuAccess = .None, uint32 sampleCount = 1, uint32 sampleQuality = 0, bool isSwapchainTarget = false) { - Texture2DDesc desc; + PixelFormat = pixelFormat; + Width = width; + Height = height; + ArraySize = arraySize; + MipLevels = mipLevels; + CpuAccess = cpuAccess; + DepthStencilFormat = depthStencilFormat; - desc.Width = width; - desc.Height = height; - desc.Format = format; - desc.ArraySize = arraySize; - desc.MipLevels = mipLevels; - // RenderTargets only can do default (I think) - desc.Usage = .Default; - desc.CpuAccess = cpuAccess; + SampleCount = sampleCount; + SampleQuality = sampleQuality; - CreateRenderTargetPlatform(desc); + IsSwapchainTarget = isSwapchainTarget; } + } + + public class RenderTarget2D : RefCounted + { + internal GraphicsContext _context; + + private RenderTarget2DDescription _description; + + public RenderTarget2DDescription Description => _description; + + public uint32 Width => _description.Width; + public uint32 Height => _description.Height; + + protected internal DepthStencilTarget _depthStenilTarget ~ _?.ReleaseRef(); - protected extern void CreateRenderTargetPlatform(Texture2DDesc desc); + // TODO: DepthStencilTarget is just a renderTarget + public DepthStencilTarget DepthStencilTarget => _depthStenilTarget; + + protected SamplerState _samplerState ~ _?.ReleaseRef(); + + public SamplerState SamplerState + { + get => _samplerState; + set + { + if(_samplerState == value) + return; + + SetReference!(_samplerState, value); + } + } + + public this(GraphicsContext context, RenderTarget2DDescription description) + { + _context = context; + _description = description; + + ApplyChanges(); + } + + /// Recreates the render target using the current description + public void ApplyChanges() + { + PlatformApplyChanges(); + } + + public extern void Resize(uint32 width, uint32 height); + + protected extern void PlatformApplyChanges(); } } diff --git a/GlitchyEngine/src/Renderer/RendererAPI.bf b/GlitchyEngine/src/Renderer/RendererAPI.bf index f39831b..27957c3 100644 --- a/GlitchyEngine/src/Renderer/RendererAPI.bf +++ b/GlitchyEngine/src/Renderer/RendererAPI.bf @@ -20,6 +20,8 @@ namespace GlitchyEngine.Renderer public extern void Clear(RenderTarget2D renderTarget, ColorRGBA clearColor); public extern void Clear(DepthStencilTarget target, float depthValue, uint8 stencilValue, DepthStencilClearFlag clearFlags); + + public extern void Clear(RenderTarget2D renderTarget, float depthValue, uint8 stencilValue, DepthStencilClearFlag clearFlags); public extern void DrawIndexed(GeometryBinding geometry);