Jelajahi Sumber

Added missing builtin functions (#83)

* Added Degrees and Radians functions to ShaderBuiltins and new constant DegreesPerRadian.

Increased default ToolChain timeout to 30s, as FXC sometimes timesout on slower systems.

* Adds Exp2 function.

* Added RSqrt function (inverse square root).

* Added Step function.

* Added Sign function.

* Added Metal implementations for Degrees and Radians builtin functions.
Craig Dean 7 tahun lalu
induk
melakukan
b17d8a8a99

+ 41 - 1
src/ShaderGen.Primitives/ShaderBuiltins.cs

@@ -13,6 +13,8 @@ namespace ShaderGen
 
         public const float E = (float)Math.E;
 
+        public const float DegreesPerRadian = 57.2957795130823f;
+
         /*
          * Misc
          */
@@ -173,12 +175,24 @@ namespace ShaderGen
         public static Vector3 Cosh(Vector3 value) => new Vector3((float)Math.Cosh(value.X), (float)Math.Cosh(value.Y), (float)Math.Cosh(value.Z));
         public static Vector4 Cosh(Vector4 value) => new Vector4((float)Math.Cosh(value.X), (float)Math.Cosh(value.Y), (float)Math.Cosh(value.Z), (float)Math.Cosh(value.W));
 
+        // Degrees
+        public static float Degrees(float value) => value * DegreesPerRadian;
+        public static Vector2 Degrees(Vector2 value) => new Vector2(value.X * DegreesPerRadian, value.Y * DegreesPerRadian);
+        public static Vector3 Degrees(Vector3 value) => new Vector3(value.X * DegreesPerRadian, value.Y * DegreesPerRadian, value.Z * DegreesPerRadian);
+        public static Vector4 Degrees(Vector4 value) => new Vector4(value.X * DegreesPerRadian, value.Y * DegreesPerRadian, value.Z * DegreesPerRadian, value.W * DegreesPerRadian);
+
         // Exp
         public static float Exp(float value) => (float)Math.Exp(value);
         public static Vector2 Exp(Vector2 value) => new Vector2((float)Math.Exp(value.X), (float)Math.Exp(value.Y));
         public static Vector3 Exp(Vector3 value) => new Vector3((float)Math.Exp(value.X), (float)Math.Exp(value.Y), (float)Math.Exp(value.Z));
         public static Vector4 Exp(Vector4 value) => new Vector4((float)Math.Exp(value.X), (float)Math.Exp(value.Y), (float)Math.Exp(value.Z), (float)Math.Exp(value.W));
 
+        // Exp2
+        public static float Exp2(float value) => (float) Math.Pow(2.0, value);
+        public static Vector2 Exp2(Vector2 value) => new Vector2((float) Math.Pow(2.0, value.X), (float) Math.Pow(2.0, value.Y));
+        public static Vector3 Exp2(Vector3 value) => new Vector3((float) Math.Pow(2.0, value.X), (float) Math.Pow(2.0, value.Y), (float) Math.Pow(2.0, value.Z));
+        public static Vector4 Exp2(Vector4 value) => new Vector4((float) Math.Pow(2.0, value.X), (float) Math.Pow(2.0, value.Y), (float) Math.Pow(2.0, value.Z), (float) Math.Pow(2.0, value.W));
+
         // Floor
         public static float Floor(float value) => (float)Math.Floor(value);
         public static Vector2 Floor(Vector2 value) => new Vector2((float)Math.Floor(value.X), (float)Math.Floor(value.Y));
@@ -279,22 +293,41 @@ namespace ShaderGen
         // Pow
         [MethodImpl(MethodImplOptions.AggressiveInlining)]
         public static float Pow(float x, float y) => (float)Math.Pow(Math.Abs(x), y);
-        public static Vector2 Pow(Vector2 y, Vector2 x) => new Vector2((float)Pow(y.X, x.X), Pow(y.Y, x.Y));
+        public static Vector2 Pow(Vector2 y, Vector2 x) => new Vector2(Pow(y.X, x.X), Pow(y.Y, x.Y));
         public static Vector3 Pow(Vector3 y, Vector3 x) => new Vector3(Pow(y.X, x.X), Pow(y.Y, x.Y), Pow(y.Z, x.Z));
         public static Vector4 Pow(Vector4 y, Vector4 x) => new Vector4(Pow(y.X, x.X), Pow(y.Y, x.Y), Pow(y.Z, x.Z), Pow(y.W, x.W));
 
+        // Radians
+        public static float Radians(float value) => value / DegreesPerRadian;
+        public static Vector2 Radians(Vector2 value) => new Vector2(value.X / DegreesPerRadian, value.Y / DegreesPerRadian);
+        public static Vector3 Radians(Vector3 value) => new Vector3(value.X / DegreesPerRadian, value.Y / DegreesPerRadian, value.Z / DegreesPerRadian);
+        public static Vector4 Radians(Vector4 value) => new Vector4(value.X / DegreesPerRadian, value.Y / DegreesPerRadian, value.Z / DegreesPerRadian, value.W / DegreesPerRadian);
+
         // Round
         public static float Round(float value) => (float)Math.Round(value);
         public static Vector2 Round(Vector2 value) => new Vector2((float)Math.Round(value.X), (float)Math.Round(value.Y));
         public static Vector3 Round(Vector3 value) => new Vector3((float)Math.Round(value.X), (float)Math.Round(value.Y), (float)Math.Round(value.Z));
         public static Vector4 Round(Vector4 value) => new Vector4((float)Math.Round(value.X), (float)Math.Round(value.Y), (float)Math.Round(value.Z), (float)Math.Round(value.W));
 
+        // Rsqrt
+        public static float Rsqrt(float value) => (float)(1.0/Math.Sqrt(value));
+        public static Vector2 Rsqrt(Vector2 value) => new Vector2((float)(1.0/Math.Sqrt(value.X)), (float)(1.0/Math.Sqrt(value.Y)));
+        public static Vector3 Rsqrt(Vector3 value) => new Vector3((float)(1.0/Math.Sqrt(value.X)), (float)(1.0/Math.Sqrt(value.Y)), (float)(1.0/Math.Sqrt(value.Z)));
+        public static Vector4 Rsqrt(Vector4 value) => new Vector4((float)(1.0/Math.Sqrt(value.X)), (float)(1.0/Math.Sqrt(value.Y)), (float)(1.0/Math.Sqrt(value.Z)), (float)(1.0/Math.Sqrt(value.W)));
+
         // Saturate
         public static float Saturate(float value) => Clamp(value, 0f, 1f);
         public static Vector2 Saturate(Vector2 value) => new Vector2(Clamp(value.X, 0f, 1f), Clamp(value.Y, 0f, 1f));
         public static Vector3 Saturate(Vector3 value) => new Vector3(Clamp(value.X, 0f, 1f), Clamp(value.Y, 0f, 1f), Clamp(value.Z, 0f, 1f));
         public static Vector4 Saturate(Vector4 value) => new Vector4(Clamp(value.X, 0f, 1f), Clamp(value.Y, 0f, 1f), Clamp(value.Z, 0f, 1f), Clamp(value.W, 0f, 1f));
 
+        // Sign
+        [MethodImpl(MethodImplOptions.AggressiveInlining)]
+        public static float Sign(float value) => value > 0f ? 1f : (value < 0f ? -1f : 0f);
+        public static Vector2 Sign(Vector2 value) => new Vector2(Sign(value.X), Sign(value.Y));
+        public static Vector3 Sign(Vector3 value) => new Vector3(Sign(value.X), Sign(value.Y), Sign(value.Z));
+        public static Vector4 Sign(Vector4 value) => new Vector4(Sign(value.X), Sign(value.Y), Sign(value.Z), Sign(value.W));
+
         // Sin
         public static float Sin(float value) => (float)Math.Sin(value);
         public static Vector2 Sin(Vector2 value) => new Vector2((float)Math.Sin(value.X), (float)Math.Sin(value.Y));
@@ -333,6 +366,13 @@ namespace ShaderGen
         public static Vector4 SmoothStep(Vector4 min, Vector4 max, Vector4 x) => new Vector4(SmoothStep(min.X, max.X, x.X), SmoothStep(min.Y, max.Y, x.Y), SmoothStep(min.Z, max.Z, x.Z), SmoothStep(min.W, max.W, x.W));
         public static Vector4 SmoothStep(float min, float max, Vector4 x) => new Vector4(SmoothStep(min, max, x.X), SmoothStep(min, max, x.Y), SmoothStep(min, max, x.Z), SmoothStep(min, max, x.W));
 
+        // Step
+        [MethodImpl(MethodImplOptions.AggressiveInlining)]
+        public static float Step(float x, float y) => y < x ? 0f : 1f;
+        public static Vector2 Step(Vector2 y, Vector2 x) => new Vector2(Step(y.X, x.X), Step(y.Y, x.Y));
+        public static Vector3 Step(Vector3 y, Vector3 x) => new Vector3(Step(y.X, x.X), Step(y.Y, x.Y), Step(y.Z, x.Z));
+        public static Vector4 Step(Vector4 y, Vector4 x) => new Vector4(Step(y.X, x.X), Step(y.Y, x.Y), Step(y.Z, x.Z), Step(y.W, x.W));
+
         // Tan
         public static float Tan(float value) => (float)Math.Tan(value);
         public static Vector2 Tan(Vector2 value) => new Vector2((float)Math.Tan(value.X), (float)Math.Tan(value.Y));

+ 1 - 1
src/ShaderGen.Tests/Tools/ToolChain.cs

@@ -26,7 +26,7 @@ namespace ShaderGen.Tests.Tools
         /// <summary>
         /// The default timeout in ms to allow for a tool to run.
         /// </summary>
-        public const int DefaultTimeout = 15000;
+        public const int DefaultTimeout = 30000;
 
         /// <summary>
         /// Compiles and validates code in one step.

+ 6 - 0
src/ShaderGen/Glsl/Glsl330KnownFunctions.cs

@@ -35,9 +35,11 @@ namespace ShaderGen.Glsl
                 { nameof(ShaderBuiltins.DdxFine), SimpleNameTranslator("dFdx") },
                 { nameof(ShaderBuiltins.Ddy), SimpleNameTranslator("dFdy") },
                 { nameof(ShaderBuiltins.DdyFine), SimpleNameTranslator("dFdy") },
+                { nameof(ShaderBuiltins.Degrees), SimpleNameTranslator() },
                 { nameof(ShaderBuiltins.Discard), Discard },
                 { nameof(ShaderBuiltins.DispatchThreadID), DispatchThreadID },
                 { nameof(ShaderBuiltins.Exp), SimpleNameTranslator() },
+                { nameof(ShaderBuiltins.Exp2), SimpleNameTranslator() },
                 { nameof(ShaderBuiltins.Floor), SimpleNameTranslator() },
                 { nameof(ShaderBuiltins.FMod), FMod },
                 { nameof(ShaderBuiltins.Frac), SimpleNameTranslator("fract") },
@@ -55,15 +57,19 @@ namespace ShaderGen.Glsl
                 { nameof(ShaderBuiltins.Mod), SimpleNameTranslator() },
                 { nameof(ShaderBuiltins.Mul), MatrixMul },
                 { nameof(ShaderBuiltins.Pow), Pow },
+                { nameof(ShaderBuiltins.Radians), SimpleNameTranslator() },
                 { nameof(ShaderBuiltins.Round), Round },
+                { nameof(ShaderBuiltins.Rsqrt), SimpleNameTranslator("inversesqrt") },
                 { nameof(ShaderBuiltins.Sample), Sample },
                 { nameof(ShaderBuiltins.SampleComparisonLevelZero), SampleComparisonLevelZero },
                 { nameof(ShaderBuiltins.SampleGrad), SampleGrad },
                 { nameof(ShaderBuiltins.Saturate), Saturate },
+                { nameof(ShaderBuiltins.Sign), SimpleNameTranslator() },
                 { nameof(ShaderBuiltins.Sin), SimpleNameTranslator() },
                 { nameof(ShaderBuiltins.Sinh), SimpleNameTranslator() },
                 { nameof(ShaderBuiltins.SmoothStep), SimpleNameTranslator() },
                 { nameof(ShaderBuiltins.Sqrt), SimpleNameTranslator() },
+                { nameof(ShaderBuiltins.Step), SimpleNameTranslator() },
                 { nameof(ShaderBuiltins.Store), Store },
                 { nameof(ShaderBuiltins.Tan), SimpleNameTranslator() },
                 { nameof(ShaderBuiltins.Tanh), SimpleNameTranslator() },

+ 6 - 0
src/ShaderGen/Glsl/Glsl450KnownFunctions.cs

@@ -31,6 +31,7 @@ namespace ShaderGen.Glsl
                 { nameof(ShaderBuiltins.ClipToTextureCoordinates), ClipToTextureCoordinates },
                 { nameof(ShaderBuiltins.Cos), SimpleNameTranslator() },
                 { nameof(ShaderBuiltins.Cosh), SimpleNameTranslator() },
+                { nameof(ShaderBuiltins.Degrees), SimpleNameTranslator() },
                 { nameof(ShaderBuiltins.Ddx), SimpleNameTranslator("dFdx") },
                 { nameof(ShaderBuiltins.DdxFine), SimpleNameTranslator("dFdxFine") },
                 { nameof(ShaderBuiltins.Ddy), SimpleNameTranslator("dFdy") },
@@ -38,6 +39,7 @@ namespace ShaderGen.Glsl
                 { nameof(ShaderBuiltins.Discard), Discard },
                 { nameof(ShaderBuiltins.DispatchThreadID), DispatchThreadID },
                 { nameof(ShaderBuiltins.Exp), SimpleNameTranslator() },
+                { nameof(ShaderBuiltins.Exp2), SimpleNameTranslator() },
                 { nameof(ShaderBuiltins.Floor), SimpleNameTranslator() },
                 { nameof(ShaderBuiltins.FMod), FMod },
                 { nameof(ShaderBuiltins.Frac), SimpleNameTranslator("fract") },
@@ -55,15 +57,19 @@ namespace ShaderGen.Glsl
                 { nameof(ShaderBuiltins.Mod), SimpleNameTranslator() },
                 { nameof(ShaderBuiltins.Mul), MatrixMul },
                 { nameof(ShaderBuiltins.Pow), SimpleNameTranslator() },
+                { nameof(ShaderBuiltins.Radians), SimpleNameTranslator() },
                 { nameof(ShaderBuiltins.Round), Round },
+                { nameof(ShaderBuiltins.Rsqrt), SimpleNameTranslator("inversesqrt") },
                 { nameof(ShaderBuiltins.Sample), Sample },
                 { nameof(ShaderBuiltins.SampleComparisonLevelZero), SampleComparisonLevelZero },
                 { nameof(ShaderBuiltins.SampleGrad), SampleGrad },
                 { nameof(ShaderBuiltins.Saturate), Saturate },
+                { nameof(ShaderBuiltins.Sign), SimpleNameTranslator() },
                 { nameof(ShaderBuiltins.Sin), SimpleNameTranslator() },
                 { nameof(ShaderBuiltins.Sinh), SimpleNameTranslator() },
                 { nameof(ShaderBuiltins.SmoothStep), SimpleNameTranslator() },
                 { nameof(ShaderBuiltins.Sqrt), SimpleNameTranslator() },
+                { nameof(ShaderBuiltins.Step), SimpleNameTranslator() },
                 { nameof(ShaderBuiltins.Store), Store },
                 { nameof(ShaderBuiltins.Tan), SimpleNameTranslator() },
                 { nameof(ShaderBuiltins.Tanh), SimpleNameTranslator() },

+ 6 - 0
src/ShaderGen/Glsl/GlslEs300KnownFunctions.cs

@@ -35,9 +35,11 @@ namespace ShaderGen.Glsl
                 { nameof(ShaderBuiltins.DdxFine), SimpleNameTranslator("dFdx") },
                 { nameof(ShaderBuiltins.Ddy), SimpleNameTranslator("dFdy") },
                 { nameof(ShaderBuiltins.DdyFine), SimpleNameTranslator("dFdy") },
+                { nameof(ShaderBuiltins.Degrees), SimpleNameTranslator() },
                 { nameof(ShaderBuiltins.Discard), Discard },
                 { nameof(ShaderBuiltins.DispatchThreadID), DispatchThreadID },
                 { nameof(ShaderBuiltins.Exp), SimpleNameTranslator() },
+                { nameof(ShaderBuiltins.Exp2), SimpleNameTranslator() },
                 { nameof(ShaderBuiltins.Floor), SimpleNameTranslator() },
                 { nameof(ShaderBuiltins.FMod), FMod },
                 { nameof(ShaderBuiltins.Frac), SimpleNameTranslator("fract") },
@@ -55,15 +57,19 @@ namespace ShaderGen.Glsl
                 { nameof(ShaderBuiltins.Mod), SimpleNameFloatParameterTranslator() },
                 { nameof(ShaderBuiltins.Mul), MatrixMul },
                 { nameof(ShaderBuiltins.Pow), Pow },
+                { nameof(ShaderBuiltins.Radians), SimpleNameTranslator() },
                 { nameof(ShaderBuiltins.Round), Round },
+                { nameof(ShaderBuiltins.Rsqrt), SimpleNameTranslator("inversesqrt") },
                 { nameof(ShaderBuiltins.Sample), Sample },
                 { nameof(ShaderBuiltins.SampleComparisonLevelZero), SampleComparisonLevelZero },
                 { nameof(ShaderBuiltins.SampleGrad), SampleGrad },
                 { nameof(ShaderBuiltins.Saturate), Saturate },
+                { nameof(ShaderBuiltins.Sign), SimpleNameTranslator() },
                 { nameof(ShaderBuiltins.Sin), SimpleNameTranslator() },
                 { nameof(ShaderBuiltins.Sinh), SimpleNameTranslator() },
                 { nameof(ShaderBuiltins.SmoothStep), SimpleNameTranslator() },
                 { nameof(ShaderBuiltins.Sqrt), SimpleNameTranslator() },
+                { nameof(ShaderBuiltins.Step), SimpleNameTranslator() },
                 { nameof(ShaderBuiltins.Store), Store },
                 { nameof(ShaderBuiltins.Tan), SimpleNameTranslator() },
                 { nameof(ShaderBuiltins.Tanh), SimpleNameTranslator() },

+ 2 - 1
src/ShaderGen/Glsl/GlslKnownIdentifiers.cs

@@ -14,7 +14,8 @@ namespace ShaderGen.Glsl
             Dictionary<string, string> builtinMappings = new Dictionary<string, string>()
             {
                 { nameof(ShaderBuiltins.E), "2.71828182845905" },
-                { nameof(ShaderBuiltins.PI), "3.14159265358979" }
+                { nameof(ShaderBuiltins.PI), "3.14159265358979" },
+                { nameof(ShaderBuiltins.DegreesPerRadian), "57.2957795130823" }
             };
             ret.Add("ShaderGen.ShaderBuiltins", builtinMappings);
 

+ 6 - 0
src/ShaderGen/Hlsl/HlslKnownFunctions.cs

@@ -35,9 +35,11 @@ namespace ShaderGen.Hlsl
                 { nameof(ShaderBuiltins.DdxFine), SimpleNameTranslator("ddx_fine") },
                 { nameof(ShaderBuiltins.Ddy), SimpleNameTranslator() },
                 { nameof(ShaderBuiltins.DdyFine), SimpleNameTranslator("ddy_fine") },
+                { nameof(ShaderBuiltins.Degrees), SimpleNameTranslator() },
                 { nameof(ShaderBuiltins.Discard), Discard },
                 { nameof(ShaderBuiltins.DispatchThreadID), DispatchThreadID },
                 { nameof(ShaderBuiltins.Exp), SimpleNameTranslator() },
+                { nameof(ShaderBuiltins.Exp2), SimpleNameTranslator() },
                 { nameof(ShaderBuiltins.Floor), SimpleNameTranslator() },
                 { nameof(ShaderBuiltins.FMod), SimpleNameTranslator() },
                 { nameof(ShaderBuiltins.Frac), SimpleNameTranslator() },
@@ -55,15 +57,19 @@ namespace ShaderGen.Hlsl
                 { nameof(ShaderBuiltins.Mod), Mod },
                 { nameof(ShaderBuiltins.Mul), SimpleNameTranslator() },
                 { nameof(ShaderBuiltins.Pow), Pow },
+                { nameof(ShaderBuiltins.Radians), SimpleNameTranslator() },
                 { nameof(ShaderBuiltins.Round), Round },
+                { nameof(ShaderBuiltins.Rsqrt), SimpleNameTranslator() },
                 { nameof(ShaderBuiltins.Sample), Sample },
                 { nameof(ShaderBuiltins.SampleComparisonLevelZero), SampleComparisonLevelZero },
                 { nameof(ShaderBuiltins.SampleGrad), SampleGrad },
                 { nameof(ShaderBuiltins.Saturate), SimpleNameTranslator() },
+                { nameof(ShaderBuiltins.Sign), SimpleNameTranslator() },
                 { nameof(ShaderBuiltins.Sin), SimpleNameTranslator() },
                 { nameof(ShaderBuiltins.Sinh), SimpleNameTranslator() },
                 { nameof(ShaderBuiltins.SmoothStep), SimpleNameTranslator() },
                 { nameof(ShaderBuiltins.Sqrt), SimpleNameTranslator() },
+                { nameof(ShaderBuiltins.Step), SimpleNameTranslator() },
                 { nameof(ShaderBuiltins.Store), Store },
                 { nameof(ShaderBuiltins.Tan), SimpleNameTranslator() },
                 { nameof(ShaderBuiltins.Tanh), SimpleNameTranslator() },

+ 2 - 1
src/ShaderGen/Hlsl/HlslKnownIdentifiers.cs

@@ -14,7 +14,8 @@ namespace ShaderGen.Hlsl
             Dictionary<string, string> builtinMappings = new Dictionary<string, string>()
             {
                 { nameof(ShaderBuiltins.E), "2.71828182845905" },
-                { nameof(ShaderBuiltins.PI), "3.14159265358979" }
+                { nameof(ShaderBuiltins.PI), "3.14159265358979" },
+                { nameof(ShaderBuiltins.DegreesPerRadian), "57.2957795130823" }
             };
             ret.Add("ShaderGen.ShaderBuiltins", builtinMappings);
 

+ 17 - 1
src/ShaderGen/Metal/MetalKnownFunctions.cs

@@ -35,11 +35,13 @@ namespace ShaderGen.Metal
                 {nameof(ShaderBuiltins.DdxFine), SimpleNameTranslator("dfdx")},
                 {nameof(ShaderBuiltins.Ddy), SimpleNameTranslator("dfdy")},
                 {nameof(ShaderBuiltins.DdyFine), SimpleNameTranslator("dfdy")},
+                {nameof(ShaderBuiltins.Degrees), Degrees},
                 {nameof(ShaderBuiltins.Discard), Discard},
                 {nameof(ShaderBuiltins.DispatchThreadID), DispatchThreadID},
                 {nameof(ShaderBuiltins.Exp), SimpleNameTranslator()},
+                {nameof(ShaderBuiltins.Exp2), SimpleNameTranslator()},
                 {nameof(ShaderBuiltins.Floor), SimpleNameTranslator()},
-                {nameof(ShaderBuiltins.FMod), FMod },
+                {nameof(ShaderBuiltins.FMod), FMod},
                 {nameof(ShaderBuiltins.Frac), SimpleNameTranslator("fract")},
                 {nameof(ShaderBuiltins.GroupThreadID), GroupThreadID},
                 {nameof(ShaderBuiltins.InstanceID), InstanceID},
@@ -55,15 +57,19 @@ namespace ShaderGen.Metal
                 {nameof(ShaderBuiltins.Mod), Mod},
                 {nameof(ShaderBuiltins.Mul), MatrixMul},
                 {nameof(ShaderBuiltins.Pow), Pow},
+                {nameof(ShaderBuiltins.Radians), Radians},
                 {nameof(ShaderBuiltins.Round), Round},
+                {nameof(ShaderBuiltins.Rsqrt), SimpleNameTranslator()},
                 {nameof(ShaderBuiltins.Sample), Sample},
                 {nameof(ShaderBuiltins.SampleComparisonLevelZero), SampleComparisonLevelZero},
                 {nameof(ShaderBuiltins.SampleGrad), SampleGrad},
                 {nameof(ShaderBuiltins.Saturate), SimpleNameTranslator()},
+                {nameof(ShaderBuiltins.Sign), SimpleNameTranslator()},
                 {nameof(ShaderBuiltins.Sin), SimpleNameTranslator()},
                 {nameof(ShaderBuiltins.Sinh), SimpleNameTranslator()},
                 {nameof(ShaderBuiltins.SmoothStep), SimpleNameTranslator()},
                 {nameof(ShaderBuiltins.Sqrt), SimpleNameTranslator()},
+                {nameof(ShaderBuiltins.Step), SimpleNameTranslator()},
                 {nameof(ShaderBuiltins.Store), Store},
                 {nameof(ShaderBuiltins.Tan), SimpleNameTranslator()},
                 {nameof(ShaderBuiltins.Tanh), SimpleNameTranslator()},
@@ -740,5 +746,15 @@ namespace ShaderGen.Metal
             return
                 $"{shaderType}({string.Join(",", Enumerable.Range(0, elementCount).Select(a => check.Replace("`", $"[{a}]")))})";
         }
+
+        private static string Degrees(string typename, string methodname, InvocationParameterInfo[] parameters)
+        {
+            return $"({parameters[0].Identifier}*57.2957795130823)";
+        }
+
+        private static string Radians(string typename, string methodname, InvocationParameterInfo[] parameters)
+        {
+            return $"({parameters[0].Identifier}/57.2957795130823)";
+        }
     }
 }

+ 2 - 1
src/ShaderGen/Metal/MetalKnownIdentifiers.cs

@@ -14,7 +14,8 @@ namespace ShaderGen.Metal
             Dictionary<string, string> builtinMappings = new Dictionary<string, string>()
             {
                 { nameof(ShaderBuiltins.E), "2.71828182845905" },
-                { nameof(ShaderBuiltins.PI), "3.14159265358979" }
+                { nameof(ShaderBuiltins.PI), "3.14159265358979" },
+                { nameof(ShaderBuiltins.DegreesPerRadian), "57.2957795130823" }
             };
             ret.Add("ShaderGen.ShaderBuiltins", builtinMappings);