Generator: Handle union generation and nested types as well + D3D11 magic.

This commit is contained in:
Amer Koleci
2022-09-05 14:03:56 +02:00
parent 584973b972
commit dde3ede8f0
8 changed files with 1602 additions and 184 deletions

View File

@@ -129,4 +129,5 @@ public sealed class ApiData
{
public ApiDataConstant[] Constants { get; set; }
public ApiType[] Types { get; set; }
public ApiFunction[] Functions { get; set; }
}

View File

@@ -1,12 +1,10 @@
// Copyright © Amer Koleci and Contributors.
// Licensed under the MIT License (MIT). See LICENSE in the repository root for more information.
using System.Text;
using System.Text.RegularExpressions;
using System.Xml;
using MessagePack;
using Microsoft.Windows.SDK.Win32Docs;
using Newtonsoft.Json.Linq;
namespace Generator;

View File

@@ -2,6 +2,7 @@
// Licensed under the MIT License (MIT). See LICENSE in the repository root for more information.
using System.Globalization;
using System.Linq;
using System.Text;
using Newtonsoft.Json;
@@ -97,13 +98,7 @@ public static class Program
{ "D3D_SHADER_INPUT_TYPE", "D3D_SIT" },
{ "D3D_SHADER_CBUFFER_FLAGS", "D3D_CBF" },
// D3D11
{ "D3D11_INPUT_CLASSIFICATION", "D3D11_INPUT" },
{ "D3D11_FILL_MODE", "D3D11_FILL" },
{ "D3D11_CULL_MODE", "D3D11_CULL" },
{ "D3D11_BIND_FLAG", "D3D11_BIND" },
{ "D3D11_CPU_ACCESS_FLAG", "D3D11_CPU_ACCESS" },
{ "D3D11_RESOURCE_MISC_FLAG", "D3D11_RESOURCE_MISC" },
// D3D11 -> handled in code
};
private static readonly Dictionary<string, string> s_partRenames = new()
@@ -173,6 +168,16 @@ public static class Program
{ "DXGI_FORMAT_420_OPAQUE", "Opaque420" },
{ "DXGI_OUTDUPL_COMPOSITED_UI_CAPTURE_ONLY", "CompositedUICaptureOnly" },
{ "D3D_FEATURE_LEVEL_9_1", "Level_9_1" },
// D3D11
{ "D3D11_STANDARD_MULTISAMPLE_PATTERN", "Standard" },
{ "D3D11_CENTER_MULTISAMPLE_PATTERN", "Center" },
{ "D3D11_SHADER_MIN_PRECISION_10_BIT", "Bit10" },
{ "D3D11_SHADER_MIN_PRECISION_16_BIT", "Bit16" },
{ "D3D11_SHARED_RESOURCE_TIER_0", "Tier0" },
{ "D3D11_SHARED_RESOURCE_TIER_1", "Tier1" },
{ "D3D11_SHARED_RESOURCE_TIER_2", "Tier2" },
{ "D3D11_SHARED_RESOURCE_TIER_3", "Tier3" },
};
private static readonly Dictionary<string, bool> s_generatedEnums = new()
@@ -185,12 +190,16 @@ public static class Program
{"DXGI_ENUM_MODES", true },
};
private static readonly HashSet<string> s_ignoredParts = new(StringComparer.OrdinalIgnoreCase)
private static readonly HashSet<string> s_ignoredStartParts = new(StringComparer.OrdinalIgnoreCase)
{
"DXGI",
"D3D",
"D3D10",
"D3D11",
};
private static readonly HashSet<string> s_ignoredParts = new(StringComparer.OrdinalIgnoreCase)
{
"PF" // D3D_PF_
};
@@ -211,6 +220,14 @@ public static class Program
{ "DXGI_MAP", "MapFlags" },
{ "DXGI_ENUM_MODES", "EnumModesFlags" },
{ "DXGI_MWA", "WindowAssociationFlags" },
// D3D11
{ "D3D11_BIND_FLAG", "BindFlags" },
{ "D3D11_CPU_ACCESS_FLAG", "CpuAccessFlags" },
{ "D3D11_RESOURCE_MISC_FLAG", "ResourceMiscFlags" },
{ "D3D11_MAP_FLAG", "MapFlags" },
{ "D3D11_FORMAT_SUPPORT", "FormatSupport" },
{ "D3D11_FORMAT_SUPPORT2", "FormatSupport2" },
};
private static readonly Dictionary<string, string> s_structFieldTypeRemap = new()
@@ -221,6 +238,26 @@ public static class Program
{ "DXGI_SWAP_CHAIN_DESC::Flags", "DXGI_SWAP_CHAIN_FLAG" },
{ "DXGI_SWAP_CHAIN_DESC1::BufferUsage", "Usage" },
{ "DXGI_SWAP_CHAIN_DESC1::Flags", "DXGI_SWAP_CHAIN_FLAG" },
// D3D11
{ "D3D11_BUFFER_DESC::BindFlags", "D3D11_BIND_FLAG" },
{ "D3D11_BUFFER_DESC::CPUAccessFlags", "D3D11_CPU_ACCESS_FLAG" },
{ "D3D11_BUFFER_DESC::MiscFlags", "D3D11_RESOURCE_MISC_FLAG" },
{ "D3D11_TEXTURE1D_DESC::BindFlags", "D3D11_BIND_FLAG" },
{ "D3D11_TEXTURE1D_DESC::CPUAccessFlags", "D3D11_CPU_ACCESS_FLAG" },
{ "D3D11_TEXTURE1D_DESC::MiscFlags", "D3D11_RESOURCE_MISC_FLAG" },
{ "D3D11_TEXTURE2D_DESC::BindFlags", "D3D11_BIND_FLAG" },
{ "D3D11_TEXTURE2D_DESC::CPUAccessFlags", "D3D11_CPU_ACCESS_FLAG" },
{ "D3D11_TEXTURE2D_DESC::MiscFlags", "D3D11_RESOURCE_MISC_FLAG" },
{ "D3D11_TEXTURE3D_DESC::BindFlags", "D3D11_BIND_FLAG" },
{ "D3D11_TEXTURE3D_DESC::CPUAccessFlags", "D3D11_CPU_ACCESS_FLAG" },
{ "D3D11_TEXTURE3D_DESC::MiscFlags", "D3D11_RESOURCE_MISC_FLAG" },
{ "D3D11_FEATURE_DATA_FORMAT_SUPPORT::OutFormatSupport", "D3D11_FORMAT_SUPPORT" },
{ "D3D11_FEATURE_DATA_FORMAT_SUPPORT2::OutFormatSupport2", "D3D11_FORMAT_SUPPORT2" },
};
private static readonly HashSet<string> s_visitedEnums = new();
@@ -255,9 +292,9 @@ public static class Program
}
// Generate docs
DocGenerator.Generate(new[] { "D3D" }, Path.Combine(outputPath, "Direct3D.xml"));
DocGenerator.Generate(new[] { "DXGI" }, Path.Combine(outputPath, "Dxgi.xml"));
DocGenerator.Generate(new[] { "D3D11" }, Path.Combine(outputPath, "Direct3D11.xml"));
//DocGenerator.Generate(new[] { "D3D" }, Path.Combine(outputPath, "Direct3D.xml"));
//DocGenerator.Generate(new[] { "DXGI" }, Path.Combine(outputPath, "Dxgi.xml"));
//DocGenerator.Generate(new[] { "D3D11" }, Path.Combine(outputPath, "Direct3D11.xml"));
return 0;
}
@@ -412,6 +449,23 @@ public static class Program
writer.WriteLine($"#endregion Generated Enums");
writer.WriteLine();
// Unions
writer.WriteLine($"#region Unions");
foreach (ApiType structType in api.Types.Where(item => item.Kind.ToLowerInvariant() == "union"))
{
if (s_csNameMappings.ContainsKey($"{writer.Api}.{structType.Name}"))
{
continue;
}
GenerateStruct(writer, structType);
s_visitedStructs.Add($"{writer.Api}.{structType.Name}");
}
writer.WriteLine($"#endregion Unions");
writer.WriteLine();
// Structs
writer.WriteLine($"#region Structs");
foreach (ApiType structType in api.Types.Where(item => item.Kind.ToLowerInvariant() == "struct"))
{
@@ -485,20 +539,23 @@ public static class Program
writer.WriteLine("[Flags]");
}
bool noneAdded = false;
if (csTypeName == "ShaderCacheSupportFlags")
{
}
using (writer.PushBlock($"public enum {csTypeName} : {baseTypeName}"))
{
if (isFlags &&
!enumType.Values.Any(item => GetPrettyFieldName(item.Name, enumPrefix) == "None"))
!enumType.Values.Any(item => GetEnumItemName(enumType, item, enumPrefix) == "None"))
{
writer.WriteLine("None = 0,");
noneAdded = true;
}
foreach (ApiEnumValue value in enumType.Values)
foreach (ApiEnumValue enumItem in enumType.Values)
{
if (value.Name.EndsWith("_FORCE_DWORD") ||
value.Name.EndsWith("_FORCE_UINT"))
if (enumItem.Name.EndsWith("_FORCE_DWORD") ||
enumItem.Name.EndsWith("_FORCE_UINT"))
{
continue;
}
@@ -506,34 +563,30 @@ public static class Program
// Ignore D3D10, D3D11 and D3D12 in D3D
if (enumType.Name.StartsWith("D3D_"))
{
if (value.Name.StartsWith("D3D10_") ||
value.Name.StartsWith("D3D11_") ||
value.Name.StartsWith("D3D12_"))
if (enumItem.Name.StartsWith("D3D10_") ||
enumItem.Name.StartsWith("D3D11_") ||
enumItem.Name.StartsWith("D3D12_"))
{
continue;
}
}
if (value.Name.EndsWith("_MESSAGES_START") ||
value.Name.EndsWith("_MESSAGES_END"))
if (enumItem.Name.EndsWith("_MESSAGES_START") ||
enumItem.Name.EndsWith("_MESSAGES_END"))
{
continue;
}
string enumValueName = GetPrettyFieldName(value.Name, enumPrefix);
if (enumType.Name == "D3D_SHADER_VARIABLE_TYPE")
{
}
string enumValueName = GetEnumItemName(enumType, enumItem, enumPrefix);
if (!autoGenerated)
{
writer.WriteLine($"/// <include file='../{writer.DocFileName}.xml' path='doc/member[@name=\"{enumType.Name}::{value.Name}\"]/*' />");
writer.WriteLine($"/// <include file='../{writer.DocFileName}.xml' path='doc/member[@name=\"{enumType.Name}::{enumItem.Name}\"]/*' />");
}
if (s_generateUnmanagedDocs)
{
writer.WriteLine($"/// <unmanaged>{value.Name}</unmanaged>");
writer.WriteLine($"/// <unmanaged>{enumItem.Name}</unmanaged>");
}
if (enumValueName.StartsWith("DXGI_MSG_"))
@@ -541,13 +594,29 @@ public static class Program
enumValueName = enumValueName.Substring("DXGI_MSG_".Length);
}
writer.WriteLine($"{enumValueName} = {value.Value},");
writer.WriteLine($"{enumValueName} = {enumItem.Value},");
}
}
writer.WriteLine();
}
private static string GetEnumItemName(ApiType enumType, ApiEnumValue enumItem, string enumPrefix)
{
string enumValueName = GetPrettyFieldName(enumItem.Name, enumPrefix);
// D3D11 has some enum name "issues"
// D3D11_FILL_MODE -> D3D11_FILL_*
if (enumValueName.StartsWith("D3D11_"))
{
string[] parts = enumType.Name.Split(new[] { '_' }, StringSplitOptions.RemoveEmptyEntries);
enumPrefix = string.Join("_", parts.Take(parts.Length - 1));
enumValueName = GetPrettyFieldName(enumItem.Name, enumPrefix);
}
return enumValueName;
}
private static void GenerateStruct(CodeWriter writer, ApiType structType, bool nestedType = false)
{
string csTypeName;
@@ -570,6 +639,12 @@ public static class Program
}
}
bool isUnion = structType.Kind == "Union";
if (isUnion)
{
writer.WriteLine("[StructLayout(LayoutKind.Explicit)]");
}
using (writer.PushBlock($"public partial struct {csTypeName}"))
{
int fieldIndex = 0;
@@ -588,6 +663,11 @@ public static class Program
fieldValueName = GetPrettyFieldName(field.Name, structPrefix);
}
if (structType.Name == "D3D11_OMAC")
{
fieldValueName = "Buffer";
}
string fieldTypeName = GetTypeName(field.Type);
writer.WriteLine($"/// <include file='../{writer.DocFileName}.xml' path='doc/member[@name=\"{structType.Name}::{field.Name}\"]/*' />");
@@ -616,6 +696,11 @@ public static class Program
if (canUseFixed)
{
if (isUnion)
{
writer.WriteLine("[FieldOffset(0)]");
}
writer.WriteLine($"public unsafe fixed {fieldTypeName} {fieldValueName}[{field.Type.Shape.Size}];");
}
else
@@ -660,6 +745,10 @@ public static class Program
unsafePrefix += "unsafe ";
}
if (isUnion)
{
writer.WriteLine("[FieldOffset(0)]");
}
writer.WriteLine($"public {unsafePrefix}{fieldTypeName} {fieldValueName};");
}
@@ -676,6 +765,51 @@ public static class Program
{
writer.WriteLine();
if (isUnion == false)
{
foreach (ApiType nestedTypeToGenerate in structType.NestedTypes)
{
foreach (ApiStructField field in nestedTypeToGenerate.Fields)
{
ApiStructField parentMemberAccess = structType.Fields.First(item => item.Type.Name == nestedTypeToGenerate.Name);
string fieldTypeName = GetTypeName(field.Type);
string fieldName = GetPrettyFieldName(field.Name, structPrefix);
writer.WriteLine("[UnscopedRef]");
if (fieldTypeName == "Array")
{
fieldTypeName = GetTypeName(field.Type.Child);
using (writer.PushBlock($"public unsafe Span<{fieldTypeName}> {fieldName}"))
{
writer.WriteLine("[MethodImpl(MethodImplOptions.AggressiveInlining)]");
using (writer.PushBlock("get"))
{
writer.WriteLine($"return MemoryMarshal.CreateSpan(ref {parentMemberAccess.Name}.{fieldName}[0], {field.Type.Shape.Size});");
}
}
}
else
{
using (writer.PushBlock($"public ref {fieldTypeName} {fieldName}"))
{
writer.WriteLine("[MethodImpl(MethodImplOptions.AggressiveInlining)]");
using (writer.PushBlock("get"))
{
writer.WriteLineUndindented("#if NET7_0_OR_GREATER");
writer.WriteLine($"return ref {parentMemberAccess.Name}.{fieldName};");
writer.WriteLineUndindented("#else");
writer.WriteLine($"return ref MemoryMarshal.GetReference(MemoryMarshal.CreateSpan(ref {parentMemberAccess.Name}.{fieldName}, 1));");
writer.WriteLineUndindented("#endif");
}
}
}
writer.WriteLine();
}
}
}
foreach (ApiType nestedTypeToGenerate in structType.NestedTypes)
{
GenerateStruct(writer, nestedTypeToGenerate, true);
@@ -965,7 +1099,8 @@ public static class Program
{
if (constant.Name == "_FACDXGI" ||
constant.Name == "DXGI_FORMAT_DEFINED" ||
constant.Name == "D3D11_FLOAT32_MAX")
constant.Name == "D3D11_FLOAT32_MAX" ||
constant.Name.StartsWith("D3DX11_"))
{
return true;
}
@@ -999,8 +1134,15 @@ public static class Program
string[] parts = typeName.Split(new[] { '_' }, StringSplitOptions.RemoveEmptyEntries);
var sb = new StringBuilder();
foreach (string part in parts)
for (int i = 0; i < parts.Length; i++)
{
string part = parts[i];
if (i == 0 && s_ignoredStartParts.Contains(part))
{
continue;
}
if (s_ignoredParts.Contains(part))
{
continue;
@@ -1029,9 +1171,9 @@ public static class Program
else
{
sb.Append(char.ToUpper(part[0]));
for (int i = 1; i < part.Length; i++)
for (int j = 1; j < part.Length; j++)
{
sb.Append(char.ToLower(part[i]));
sb.Append(char.ToLower(part[j]));
}
}
}
@@ -1077,12 +1219,17 @@ public static class Program
sb.Append('P');
}
int partIndex = 0;
foreach (string part in parts)
for (int i = 0; i < parts.Length; i++)
{
string part = parts[i];
if (i == 0 && s_ignoredStartParts.Contains(part))
{
continue;
}
if (s_ignoredParts.Contains(part))
{
partIndex++;
continue;
}
@@ -1172,9 +1319,9 @@ public static class Program
else
{
sb.Append(char.ToUpper(part[0]));
for (int i = 1; i < part.Length; i++)
for (int j = 1; j < part.Length; j++)
{
sb.Append(char.ToLower(part[i]));
sb.Append(char.ToLower(part[j]));
}
}
}
@@ -1182,16 +1329,19 @@ public static class Program
if (appendUnderscore)
{
if (partIndex < parts.Length - 1)
if (i < parts.Length - 1)
{
sb.Append('_');
}
partIndex++;
}
}
string prettyName = sb.ToString();
if (string.IsNullOrEmpty(prettyName))
{
return parts[0];
}
return (char.IsNumber(prettyName[0])) ? "_" + prettyName : prettyName;
}

View File

@@ -1070,6 +1070,9 @@ public enum ParameterFlags : int
#region Generated Enums
#endregion Generated Enums
#region Unions
#endregion Unions
#region Structs
/// <include file='../Direct3D.xml' path='doc/member[@name="D3D_SHADER_MACRO"]/*' />
/// <unmanaged>D3D_SHADER_MACRO</unmanaged>

File diff suppressed because it is too large Load Diff

View File

@@ -570,6 +570,9 @@ public enum CpuAccess : uint
#endregion Generated Enums
#region Unions
#endregion Unions
#region Structs
/// <include file='../Dxgi.xml' path='doc/member[@name="DXGI_RATIONAL"]/*' />
/// <unmanaged>DXGI_RATIONAL</unmanaged>

View File

@@ -1650,6 +1650,9 @@ public enum WindowAssociationFlags : uint
#endregion Generated Enums
#region Unions
#endregion Unions
#region Structs
/// <include file='../Dxgi.xml' path='doc/member[@name="DXGI_RGBA"]/*' />
/// <unmanaged>DXGI_RGBA</unmanaged>

View File

@@ -0,0 +1,57 @@
// Copyright © Amer Koleci and Contributors.
// Licensed under the MIT License (MIT). See LICENSE in the repository root for more information.
using System.Runtime.CompilerServices;
using static Win32.Graphics.Dxgi.Apis;
using static Win32.StringUtilities;
namespace Win32.Graphics.Direct3D11;
public partial struct AuthenticatedProtectionFlags
{
public partial struct _Flags_e__Struct
{
public uint ProtectionEnabled
{
[MethodImpl(MethodImplOptions.AggressiveInlining)]
get
{
return _bitfield & 0x1u;
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
set
{
_bitfield = (_bitfield & ~0x1u) | (value & 0x1u);
}
}
public uint OverlayOrFullscreenRequired
{
[MethodImpl(MethodImplOptions.AggressiveInlining)]
get
{
return (_bitfield >> 1) & 0x1u;
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
set
{
_bitfield = (_bitfield & ~(0x1u << 1)) | ((value & 0x1u) << 1);
}
}
[NativeTypeName("uint : 30")]
public uint Reserved
{
[MethodImpl(MethodImplOptions.AggressiveInlining)]
get
{
return (_bitfield >> 2) & 0x3FFFFFFFu;
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
set
{
_bitfield = (_bitfield & ~(0x3FFFFFFFu << 2)) | ((value & 0x3FFFFFFFu) << 2);
}
}
}
}