A game framework written with osu! in mind.
1// Copyright (c) ppy Pty Ltd <contact@ppy.sh>. Licensed under the MIT Licence.
2// See the LICENCE file in the repository root for full licence text.
3
4using System;
5using System.Collections.Generic;
6using System.Linq;
7using osuTK;
8
9namespace osu.Framework.Graphics.Shaders
10{
11 internal static class GlobalPropertyManager
12 {
13 private static readonly HashSet<Shader> all_shaders = new HashSet<Shader>();
14 private static readonly IUniformMapping[] global_properties;
15
16 static GlobalPropertyManager()
17 {
18 var values = Enum.GetValues(typeof(GlobalProperty)).OfType<GlobalProperty>().ToArray();
19
20 global_properties = new IUniformMapping[values.Length];
21
22 global_properties[(int)GlobalProperty.ProjMatrix] = new UniformMapping<Matrix4>("g_ProjMatrix");
23 global_properties[(int)GlobalProperty.MaskingRect] = new UniformMapping<Vector4>("g_MaskingRect");
24 global_properties[(int)GlobalProperty.ToMaskingSpace] = new UniformMapping<Matrix3>("g_ToMaskingSpace");
25 global_properties[(int)GlobalProperty.CornerRadius] = new UniformMapping<float>("g_CornerRadius");
26 global_properties[(int)GlobalProperty.CornerExponent] = new UniformMapping<float>("g_CornerExponent");
27 global_properties[(int)GlobalProperty.BorderThickness] = new UniformMapping<float>("g_BorderThickness");
28 global_properties[(int)GlobalProperty.BorderColour] = new UniformMapping<Vector4>("g_BorderColour");
29 global_properties[(int)GlobalProperty.MaskingBlendRange] = new UniformMapping<float>("g_MaskingBlendRange");
30 global_properties[(int)GlobalProperty.AlphaExponent] = new UniformMapping<float>("g_AlphaExponent");
31 global_properties[(int)GlobalProperty.EdgeOffset] = new UniformMapping<Vector2>("g_EdgeOffset");
32 global_properties[(int)GlobalProperty.DiscardInner] = new UniformMapping<bool>("g_DiscardInner");
33 global_properties[(int)GlobalProperty.InnerCornerRadius] = new UniformMapping<float>("g_InnerCornerRadius");
34 global_properties[(int)GlobalProperty.GammaCorrection] = new UniformMapping<bool>("g_GammaCorrection");
35 global_properties[(int)GlobalProperty.WrapModeS] = new UniformMapping<int>("g_WrapModeS");
36 global_properties[(int)GlobalProperty.WrapModeT] = new UniformMapping<int>("g_WrapModeT");
37
38 // Backbuffer internals
39 global_properties[(int)GlobalProperty.BackbufferDraw] = new UniformMapping<bool>("g_BackbufferDraw");
40 }
41
42 /// <summary>
43 /// Sets a uniform for all shaders that contain this property.
44 /// <para>Any future-initialized shaders will also have this uniform set.</para>
45 /// </summary>
46 /// <param name="property">The uniform.</param>
47 /// <param name="value">The uniform value.</param>
48 public static void Set<T>(GlobalProperty property, T value)
49 where T : struct, IEquatable<T>
50 {
51 ((UniformMapping<T>)global_properties[(int)property]).UpdateValue(ref value);
52 }
53
54 public static void Register(Shader shader)
55 {
56 if (!all_shaders.Add(shader)) return;
57
58 // transfer all existing global properties across.
59 foreach (var global in global_properties)
60 {
61 if (!shader.Uniforms.TryGetValue(global.Name, out IUniform uniform))
62 continue;
63
64 global.LinkShaderUniform(uniform);
65 }
66 }
67
68 public static void Unregister(Shader shader)
69 {
70 if (!all_shaders.Remove(shader)) return;
71
72 foreach (var global in global_properties)
73 {
74 if (!shader.Uniforms.TryGetValue(global.Name, out IUniform uniform))
75 continue;
76
77 global.UnlinkShaderUniform(uniform);
78 }
79 }
80
81 /// <summary>
82 /// Check whether a global uniform exists with the specified name.
83 /// </summary>
84 /// <param name="name">The name to check</param>
85 /// <returns>Whether a global exists.</returns>
86 public static bool CheckGlobalExists(string name) => global_properties.Any(m => m.Name == name);
87 }
88}