diff --git a/.silktouch/openal-clangsharp.stout b/.silktouch/openal-clangsharp.stout
index cd15a37e8e..994e242e2e 100644
Binary files a/.silktouch/openal-clangsharp.stout and b/.silktouch/openal-clangsharp.stout differ
diff --git a/.silktouch/opengl-clangsharp.stout b/.silktouch/opengl-clangsharp.stout
index 9134b29332..0696b43007 100644
Binary files a/.silktouch/opengl-clangsharp.stout and b/.silktouch/opengl-clangsharp.stout differ
diff --git a/.silktouch/vulkan-clangsharp.stout b/.silktouch/vulkan-clangsharp.stout
index b6dc0b1f4a..d905b7ace2 100644
Binary files a/.silktouch/vulkan-clangsharp.stout and b/.silktouch/vulkan-clangsharp.stout differ
diff --git a/generator.json b/generator.json
index 83293d8003..8bbae05cda 100644
--- a/generator.json
+++ b/generator.json
@@ -147,6 +147,7 @@
"SpecPath": "eng/submodules/opengl/xml/gl.xml",
"Namespace": "Silk.NET.OpenGL",
"TypeMap": {
+ "GLenum": "uint",
"TraceMaskMESA": "uint",
"PathRenderingTokenNV": "byte",
"PathCoordType": "byte"
@@ -252,6 +253,10 @@
"MixKhronosData": {
"SpecPath": "eng/submodules/openal-soft/registry/xml/al.xml",
"Namespace": "Silk.NET.OpenAL",
+ "TypeMap": {
+ "ALenum": "uint",
+ "ALCenum": "uint"
+ },
"NonStandardExtensionNomenclature": true,
"Vendors": [
"SOFT",
diff --git a/sources/OpenGL/OpenGL/Enums/FragmentShaderDestMask.gen.cs b/sources/OpenGL/OpenGL/Enums/FragmentShaderDestMask.gen.cs
index de8a534448..5a3ac06402 100644
--- a/sources/OpenGL/OpenGL/Enums/FragmentShaderDestMask.gen.cs
+++ b/sources/OpenGL/OpenGL/Enums/FragmentShaderDestMask.gen.cs
@@ -8,17 +8,18 @@
namespace Silk.NET.OpenGL;
[NativeName("FragmentShaderDestMaskATI")]
+[Flags]
public enum FragmentShaderDestMask : uint
{
[NativeName("GL_NONE")]
- None = 0,
+ None = 0x0,
[NativeName("GL_RED_BIT_ATI")]
- RedBitATI = 1,
+ RedBitATI = 0x1,
[NativeName("GL_GREEN_BIT_ATI")]
- GreenBitATI = 2,
+ GreenBitATI = 0x2,
[NativeName("GL_BLUE_BIT_ATI")]
- BlueBitATI = 4,
+ BlueBitATI = 0x4,
}
diff --git a/sources/OpenGL/OpenGL/Enums/FragmentShaderDestModMask.gen.cs b/sources/OpenGL/OpenGL/Enums/FragmentShaderDestModMask.gen.cs
index 59bc20c93d..cf98b9ca92 100644
--- a/sources/OpenGL/OpenGL/Enums/FragmentShaderDestModMask.gen.cs
+++ b/sources/OpenGL/OpenGL/Enums/FragmentShaderDestModMask.gen.cs
@@ -8,29 +8,30 @@
namespace Silk.NET.OpenGL;
[NativeName("FragmentShaderDestModMaskATI")]
+[Flags]
public enum FragmentShaderDestModMask : uint
{
[NativeName("GL_NONE")]
- None = 0,
+ None = 0x0,
[NativeName("GL_2X_BIT_ATI")]
- X2XBitATI = 1,
+ X2XBitATI = 0x1,
[NativeName("GL_4X_BIT_ATI")]
- X4XBitATI = 2,
+ X4XBitATI = 0x2,
[NativeName("GL_8X_BIT_ATI")]
- X8XBitATI = 4,
+ X8XBitATI = 0x4,
[NativeName("GL_HALF_BIT_ATI")]
- HalfBitATI = 8,
+ HalfBitATI = 0x8,
[NativeName("GL_QUARTER_BIT_ATI")]
- QuarterBitATI = 16,
+ QuarterBitATI = 0x10,
[NativeName("GL_EIGHTH_BIT_ATI")]
- EighthBitATI = 32,
+ EighthBitATI = 0x20,
[NativeName("GL_SATURATE_BIT_ATI")]
- SaturateBitATI = 64,
+ SaturateBitATI = 0x40,
}
diff --git a/sources/OpenGL/OpenGL/Enums/PathFontStyle.gen.cs b/sources/OpenGL/OpenGL/Enums/PathFontStyle.gen.cs
index 0243f93931..63ade9981e 100644
--- a/sources/OpenGL/OpenGL/Enums/PathFontStyle.gen.cs
+++ b/sources/OpenGL/OpenGL/Enums/PathFontStyle.gen.cs
@@ -8,14 +8,15 @@
namespace Silk.NET.OpenGL;
[NativeName("PathFontStyle")]
+[Flags]
public enum PathFontStyle : uint
{
[NativeName("GL_NONE")]
- None = 0,
+ None = 0x0,
[NativeName("GL_BOLD_BIT_NV")]
- BoldBitNV = 1,
+ BoldBitNV = 0x1,
[NativeName("GL_ITALIC_BIT_NV")]
- ItalicBitNV = 2,
+ ItalicBitNV = 0x2,
}
diff --git a/sources/SilkTouch/SilkTouch/Mods/MixKhronosData.cs b/sources/SilkTouch/SilkTouch/Mods/MixKhronosData.cs
index 85dc14d268..0c26dd5429 100644
--- a/sources/SilkTouch/SilkTouch/Mods/MixKhronosData.cs
+++ b/sources/SilkTouch/SilkTouch/Mods/MixKhronosData.cs
@@ -440,22 +440,55 @@ rsp with
return Task.FromResult(rsps);
}
- /// The name of the group. This is the name used for the C# enum.
- /// The native name of the group, if available. This is the name used for the [NativeName] attribute.
- ///
- ///
- ///
- ///
- ///
- internal record EnumGroup(
- string Name,
- string? NativeName,
- string? Type,
- List Enums,
- bool KnownBitmask,
- string? ExclusiveVendor,
- string? Namespace
- );
+ ///
+ /// Contains information about a group of enums.
+ ///
+ ///
+ /// There are two bitmask properties to better handle OpenGL-style enums.
+ /// Some enums are explicitly stated to be bitmasks while some have to be inferred.
+ ///
+ internal record EnumGroup
+ {
+ ///
+ /// The name of the group. This is the name used for the C# enum.
+ ///
+ public required string Name { get; init; }
+
+ ///
+ /// The native name of the group. This is the name used for the [NativeName] attribute.
+ ///
+ public required string NativeName { get; init; }
+
+ ///
+ /// The base type of the group.
+ ///
+ public string? BaseType { get; init; }
+
+ ///
+ /// Members of this group extracted from other parts of the generated bindings.
+ ///
+ public List Enums { get; init; } = [];
+
+ ///
+ /// Whether the group is explicitly known to be a bitmask, i.e., it is stated in the XML spec.
+ ///
+ public bool IsDefinitelyBitmask { get; init; }
+
+ ///
+ /// Whether the group is likely a bitmask based on heuristics.
+ ///
+ public bool IsMaybeBitmask { get; init; }
+
+ ///
+ /// The identified exclusive vendor for the group. Eg: NV.
+ ///
+ public string? ExclusiveVendor { get; init; }
+
+ ///
+ /// The namespace for the group. Eg: GL.
+ ///
+ public string? Namespace { get; init; }
+ }
private record ProfileEvaluation(
Version? StartVersion,
@@ -1544,7 +1577,7 @@ private class RewriterPhase1(JobData job, ILogger logger) : CSharpSyntaxRewriter
{
if (!AlreadyPresentGroups.Contains(groupName))
{
- var baseType = groupInfo.Type ?? groupName;
+ var baseType = groupInfo.BaseType ?? groupName;
while (job.TypeMap.TryGetValue(baseType, out var ty))
{
baseType = ty;
@@ -1759,7 +1792,10 @@ .. node.Members.Where(m =>
);
}
- if (job.Groups.TryGetValue(identifier, out var group) && group.KnownBitmask)
+ if (
+ job.Groups.TryGetValue(identifier, out var group)
+ && (group.IsDefinitelyBitmask || group.IsMaybeBitmask)
+ )
{
// Add [Flags] attribute
var flagsAttribute = AttributeList(
@@ -2161,9 +2197,6 @@ internal void ReadGroups(XDocument doc, JobData data, HashSet vendors)
// this information will mostly be used to enhance the enums scraped from the headers (eg: native name and bitmask information).
var anyNamespaced =
doc.Element("registry")?.Elements("enums").Attributes("namespace").Any() ?? false;
- var anyGLStyleGroups =
- doc.Element("registry")?.Elements("enums").Elements("enum").Attributes("group").Any()
- ?? false;
var likelyOpenCL = false; // OpenCL specific
var topLevelIntentionalExclusions = new HashSet(); // OpenCL specific
@@ -2174,24 +2207,46 @@ internal void ReadGroups(XDocument doc, JobData data, HashSet vendors)
var isBitmask = block.Attribute("type")?.Value == "bitmask";
// OpenGL/EGL/WGL/GLX namespace
- var enumNamespace = block.Attribute("namespace")?.Value;
- var groupName =
- enumNamespace is not null && !enumNamespace.All(char.IsUpper)
- ? enumNamespace
- : null;
+ var groupName = block.Attribute("group")?.Value;
var nativeName = groupName;
+ var enumNamespace = block.Attribute("namespace")?.Value;
+ var baseType = enumNamespace != null ? $"{enumNamespace}enum" : null;
- // OpenGL-style enums have an uint base type
- var baseType = anyGLStyleGroups ? "uint" : null;
+ string? namespaceGroupName = null;
+ if (enumNamespace != null)
+ {
+ if (!enumNamespace.All(char.IsUpper))
+ {
+ // Use the namespace name directly if it is not all uppercase
+ // Eg: WGLLayerPlaneMask
+ namespaceGroupName = enumNamespace;
+ }
+ else
+ {
+ // Otherwise, suffix the name with -Enum
+ // Eg: GLEnum, ALEnum, WGLEnum
+ namespaceGroupName = $"{enumNamespace}Enum";
+ }
+ }
- // Create an ungrouped group as well i.e. GLEnum, WGLEnum, etc
- if (enumNamespace is not null)
+ // Create a group for the namespace as well i.e. GLEnum, WGLEnum, etc
+ if (namespaceGroupName is not null)
{
- groupName ??= $"{enumNamespace}Enum";
- nativeName ??= $"{enumNamespace}enum";
+ if (!data.Groups.TryGetValue(namespaceGroupName, out var namespaceGroup))
+ {
+ namespaceGroup = new EnumGroup()
+ {
+ Name = namespaceGroupName,
+ NativeName = $"{enumNamespace}enum",
+ BaseType = baseType,
+ Namespace = enumNamespace,
+ };
+
+ data.Groups[namespaceGroupName] = namespaceGroup;
+ }
}
- // OpenCL enum name
+ // Vulkan/OpenXR/OpenCL enum name
if (!anyNamespaced)
{
groupName ??= block.Attribute("name")?.Value;
@@ -2213,7 +2268,9 @@ internal void ReadGroups(XDocument doc, JobData data, HashSet vendors)
// skip over the block. We continue on in the top-level case to permanently prevent any group operations
// from occurring on the top-level intentional exclusions because they're special numbers/constants.
var topLevelIntentionalExclusion =
- groupName is not null && IsIntentionalExclusion(groupName);
+ groupName != null
+ && namespaceGroupName == null
+ && IsIntentionalExclusion(groupName);
static bool IsIntentionalExclusion(string groupName) =>
groupName.StartsWith("Constants") // these are constants
|| groupName is "MiscNumbers" or "SpecialNumbers";
@@ -2230,46 +2287,49 @@ static bool IsUngroupable(string groupName) =>
}
// Initialize the group before enum members are parsed below
- // This ensures two things:
+ // This ensures 3 things:
// 1. The native name is correct
- // 2. Empty groups are recorded properly
- if (
- groupName != null
- && !IsUngroupable(groupName)
- && !data.Groups.ContainsKey(groupName)
- )
+ // 2. Whether the enum is a bitmask is correct
+ // 3. Empty groups are recorded properly
+ if (groupName != null && !IsUngroupable(groupName))
{
- data.Groups[groupName] = new EnumGroup(
- groupName,
- nativeName,
- baseType,
- [],
- isBitmask,
- VendorFromString(groupName, vendors),
- enumNamespace
- );
+ data.Groups[groupName] = data.Groups.TryGetValue(groupName, out var group)
+ ? group with
+ {
+ IsDefinitelyBitmask = isBitmask,
+ }
+ : new EnumGroup()
+ {
+ Name = groupName,
+ NativeName = nativeName ?? groupName,
+ BaseType = baseType,
+
+ IsDefinitelyBitmask = isBitmask,
+ ExclusiveVendor = VendorFromString(groupName, vendors),
+ Namespace = enumNamespace,
+ };
}
// Parse enum members
- foreach (var @enum in block.Elements("enum"))
+ foreach (var member in block.Elements("enum"))
{
- var enumName =
- @enum.Attribute("name")?.Value
+ var memberName =
+ member.Attribute("name")?.Value
?? throw new InvalidDataException("Expected \"name\" attribute on .");
if (topLevelIntentionalExclusion)
{
- topLevelIntentionalExclusions.Add(enumName);
+ topLevelIntentionalExclusions.Add(memberName);
continue;
}
// Get the group hash set for this enum.
- if (!data.EnumsToGroups.TryGetValue(enumName, out var enumToGroups))
+ if (!data.EnumsToGroups.TryGetValue(memberName, out var enumToGroups))
{
- data.EnumsToGroups[enumName] = enumToGroups = [];
+ data.EnumsToGroups[memberName] = enumToGroups = [];
}
// Parse OpenGL-style groups
- var glGroups = @enum
+ var additionalGroups = member
.Attribute("group")
?.Value.Split(
_listSeparators,
@@ -2277,46 +2337,62 @@ static bool IsUngroupable(string groupName) =>
);
// Get the vendor (if the enum name ends with a vendor that is).
- var thisVendor = VendorFromString(enumName, vendors);
+ var memberVendor = VendorFromString(memberName, vendors);
// Add the enum member to the namespace enum, the main enum group, and its additional OpenGL-style groups
- var memberGroups = (groupName is null ? Enumerable.Empty() : [groupName])
- .Concat(block.Attribute("group")?.Value is { Length: > 0 } g ? [g] : [])
- .Concat(glGroups ?? [])
- .Distinct();
- foreach (var group in memberGroups)
+ var memberGroupNames = new HashSet();
+ if (namespaceGroupName != null)
{
- if (IsUngroupable(group))
+ memberGroupNames.Add(namespaceGroupName);
+ }
+
+ if (groupName != null)
+ {
+ memberGroupNames.Add(groupName);
+ }
+
+ if (additionalGroups != null)
+ {
+ memberGroupNames.UnionWith(additionalGroups);
+ }
+
+ foreach (var memberGroupName in memberGroupNames)
+ {
+ if (IsUngroupable(memberGroupName))
{
continue;
}
// Update the group info.
- data.Groups[group] = data.Groups.TryGetValue(group, out var groupInfo)
- ? groupInfo with
+ data.Groups[memberGroupName] = data.Groups.TryGetValue(
+ memberGroupName,
+ out var memberGroup
+ )
+ ? memberGroup with
{
- KnownBitmask = isBitmask && groupInfo.KnownBitmask,
+ IsMaybeBitmask = isBitmask && memberGroup.IsMaybeBitmask,
ExclusiveVendor =
- thisVendor is not null && groupInfo.ExclusiveVendor == thisVendor
- ? thisVendor
+ memberVendor is not null
+ && memberGroup.ExclusiveVendor == memberVendor
+ ? memberVendor
: null,
Namespace =
- enumNamespace is not null && groupInfo.Namespace == enumNamespace
+ enumNamespace is not null && memberGroup.Namespace == enumNamespace
? enumNamespace
: null,
}
- : new EnumGroup(
- group,
- group,
- baseType,
- [],
- isBitmask,
- thisVendor,
- enumNamespace
- );
+ : new EnumGroup()
+ {
+ Name = memberGroupName,
+ NativeName = memberGroupName,
+ BaseType = baseType,
+ IsMaybeBitmask = isBitmask,
+ ExclusiveVendor = memberVendor,
+ Namespace = enumNamespace,
+ };
// Mark this enum.
- enumToGroups.Add(group);
+ enumToGroups.Add(memberGroupName);
}
}
}
@@ -2460,16 +2536,18 @@ var @enum in doc.Elements("registry")
// it's actually correct for once.
if (!data.Groups.ContainsKey(@enum.Value))
{
- data.Groups[@enum.Value] = new EnumGroup(
- @enum.Value,
- @enum.Value,
+ data.Groups[@enum.Value] = new EnumGroup()
+ {
+ Name = @enum.Value,
+ NativeName = @enum.Value,
// cl_properties and cl_bitfield are both cl_ulong which is ulong
- "ulong",
- [],
- @enum.Parent?.Element("type")?.Value == "cl_bitfield",
- VendorFromString(@enum.Value, vendors),
- null
- );
+ // We currently use cl_bitfield to represent the backing type of OpenCL enums
+ // Decision was made here: https://github.com/dotnet/Silk.NET/pull/2534#discussion_r2686840153
+ BaseType = "cl_bitfield",
+
+ IsDefinitelyBitmask = @enum.Parent?.Element("type")?.Value == "cl_bitfield",
+ ExclusiveVendor = VendorFromString(@enum.Value, vendors),
+ };
}
}
@@ -2626,16 +2704,16 @@ is var splitList
}
else
{
- data.Groups[groupStr] = new EnumGroup(
- groupStr,
- groupStr,
- null,
- [],
- (typeStr is not null && typeStr.Contains("bitfield"))
+ data.Groups[groupStr] = new EnumGroup()
+ {
+ Name = groupStr,
+ NativeName = groupStr,
+
+ IsDefinitelyBitmask =
+ (typeStr is not null && typeStr.Contains("bitfield"))
|| group.Contains("flags"),
- thisVendor,
- null
- );
+ ExclusiveVendor = thisVendor,
+ };
}
// Get the group hash set for this enum.
diff --git a/tests/SilkTouch/SilkTouch/Khronos/MixKhronosDataTests.cs b/tests/SilkTouch/SilkTouch/Khronos/MixKhronosDataTests.cs
index b9a7cf62ef..e3be2fda66 100644
--- a/tests/SilkTouch/SilkTouch/Khronos/MixKhronosDataTests.cs
+++ b/tests/SilkTouch/SilkTouch/Khronos/MixKhronosDataTests.cs
@@ -447,15 +447,13 @@ public enum GLEnum { }
{
{
"GLEnum",
- new MixKhronosData.EnumGroup(
- "GLEnum",
- "GLenum",
- "Glenum",
- [],
- false,
- null,
- "GL"
- )
+ new MixKhronosData.EnumGroup()
+ {
+ Name = "GLEnum",
+ NativeName = "GLenum",
+ BaseType = "GLenum",
+ Namespace = "GL",
+ }
},
},
},