From 7e3bb932fc161edc38c9208a6f3e0c5e1dc68567 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Simon=20L=C3=BCbe=C3=9F?= Date: Mon, 8 Feb 2021 19:36:21 +0100 Subject: [PATCH] Added simple SamplerStateManager --- GlitchyEngine/src/Application.bf | 7 ++ GlitchyEngine/src/Renderer/SamplerState.bf | 88 +++++++++++++++++++++- Sandbox/src/SandboxApp.bf | 2 +- 3 files changed, 94 insertions(+), 3 deletions(-) diff --git a/GlitchyEngine/src/Application.bf b/GlitchyEngine/src/Application.bf index d44dd8f..16585d0 100644 --- a/GlitchyEngine/src/Application.bf +++ b/GlitchyEngine/src/Application.bf @@ -36,6 +36,8 @@ namespace GlitchyEngine _rendererApi = new RendererAPI(); _rendererApi.Context = _window.Context; + SamplerStateManager.Init(_window.Context); + RenderCommand.RendererAPI = _rendererApi; Renderer.Init(_window.Context); @@ -44,6 +46,11 @@ namespace GlitchyEngine PushOverlay(_imGuiLayer); } + public ~this() + { + SamplerStateManager.Uninit(); + } + public void OnEvent(Event e) { EventDispatcher dispatcher = scope .(e); diff --git a/GlitchyEngine/src/Renderer/SamplerState.bf b/GlitchyEngine/src/Renderer/SamplerState.bf index a50a578..9ed249b 100644 --- a/GlitchyEngine/src/Renderer/SamplerState.bf +++ b/GlitchyEngine/src/Renderer/SamplerState.bf @@ -1,8 +1,12 @@ using System; using GlitchyEngine.Math; +using System.Collections; namespace GlitchyEngine.Renderer { + /** + * Defines the filter function used when sampling from a texture. + */ public enum FilterFunction { /// Use point filtering (nearest neighbor) for sampling. @@ -88,7 +92,7 @@ namespace GlitchyEngine.Renderer MirrorOnce } - public struct SamplerStateDescription + public struct SamplerStateDescription : IHashable { public FilterFunction MinFilter = .Linear; public FilterFunction MagFilter = .Linear; @@ -126,12 +130,84 @@ namespace GlitchyEngine.Renderer * Clamping value used if FilterMode.Anisotropic is specified in the Filters. * Valid values are between 1 and 16. */ - public uint32 MaxAnisotropy = 1; // TODO: we could use a smaller int + public uint8 MaxAnisotropy = 1; // TODO: we could use a smaller int /** * Border color to use if TextureAddressMode.Border is specified for AddressModeU, AddressModeV, or AddressModeW. */ public ColorRGBA BorderColor = .White; + + public int GetHashCode() + { + // Put integers into one integer + int intHash = ((int)MinFilter) | ((int)MagFilter << 2) | ((int)MipFilter << 4) | ((int)FilterMode << 6) | ((int)ComparisonFunction << 8) | + ((int)AddressModeU << 12) | ((int)AddressModeU << 15) | ((int)AddressModeU << 18) | ((int)(MaxAnisotropy & 0x1F) << 21); // (26 bit) + + // Put BorderColor into hash. + int colorHash = ((BorderColor.R.GetHashCode() * 397 ^ BorderColor.G.GetHashCode()) * 397 ^ BorderColor.B.GetHashCode()) * 397 ^ BorderColor.A.GetHashCode(); + + return (((colorHash * 397 ^ MipLODBias.GetHashCode()) * 397 ^ MipMinLOD.GetHashCode()) * 397 ^ MipMaxLOD.GetHashCode()) * 397 ^ intHash; + } + } + + public static class SamplerStateManager + { + static GraphicsContext _context; + + static Dictionary _samplers; + + public static void Init(GraphicsContext context) + { + _context = context..AddRef(); + _samplers = new .(); + } + + public static void Uninit() + { + _context?.ReleaseRef(); + + delete _samplers; + _samplers = null; + } + + /** + * Returns a Sampler State that has the specified settings. + * @param desc The Struct containing the sampler state options. + * @returns A SamplerState with the given options. + * @remarks This Function increases the SamplerStates reference counter, so remember to release it. + */ + public static SamplerState GetSampler(SamplerStateDescription desc) + { + Log.EngineLogger.AssertDebug(_samplers != null, "SamplerStateManager was not initialized."); + + if(_samplers.TryGetValue(desc, let sampler)) + { + return sampler..AddRef(); + } + + SamplerState newState = new SamplerState(_context, desc); + ManageSampler(newState); + + return newState; + } + + public static void ManageSampler(SamplerState samplerState) + { + Log.EngineLogger.AssertDebug(_samplers != null, "SamplerStateManager was not initialized."); + + _samplers.Add(samplerState.Description, samplerState); + } + + /** + * Removes the given SamplerState from the manager. + * Only allows to remove samplerState with a reference count of 0. + */ + internal static void Remove(SamplerState samplerState) + { + Log.EngineLogger.AssertDebug(samplerState.RefCount == 0, "Tried to delete sampler with nonzero reference count."); + + _samplers?.Remove(samplerState.Description); + } } public class SamplerState : RefCounted @@ -148,6 +224,9 @@ namespace GlitchyEngine.Renderer public FilterFunction MipFilter => _desc.MipFilter; [Inline] public FilterMode FilterMode => _desc.FilterMode; + + [Inline] + public SamplerStateDescription Description => _desc; protected this(GraphicsContext context) { @@ -161,6 +240,11 @@ namespace GlitchyEngine.Renderer PlatformCreateSamplerState(); } + public ~this() + { + SamplerStateManager.[Friend]Remove(this); + } + /// Creates the platform specific Sampler State protected extern void PlatformCreateSamplerState(); diff --git a/Sandbox/src/SandboxApp.bf b/Sandbox/src/SandboxApp.bf index 5420c97..19ca955 100644 --- a/Sandbox/src/SandboxApp.bf +++ b/Sandbox/src/SandboxApp.bf @@ -194,7 +194,7 @@ namespace Sandbox _texture = new Texture2D(_context, "content/Textures/Checkerboard.dds"); - let sampler = new SamplerState(_context, + let sampler = SamplerStateManager.GetSampler( SamplerStateDescription() { MagFilter = .Point