add bindings

This commit is contained in:
2026-07-22 00:32:44 +02:00
commit 23bca0e23e
13 changed files with 3454 additions and 0 deletions
+297
View File
@@ -0,0 +1,297 @@
using System;
using System.IO;
using System.Collections;
using System.Diagnostics;
using Cpp2Beef;
using LibClang;
namespace KTX.Setup;
class ExampleGenerator : Cpp2BeefGenerator, this(Span<char8*> args)
{
protected override Span<char8*> Args => args;
protected override Flags Flags => .None;
StreamWriter ktxWriter = new .()..Create("../src/KTX.bf")..Write("""
// This file was generated by Cpp2Beef
using System;
using System.Interop;
namespace KTX;
""") ~ delete _;
StreamWriter ktxVulkanWriter = new .()..Create("../src/KTXVulkan.bf")..Write("""
// This file was generated by Cpp2Beef
using System;
using System.Interop;
namespace KTX;
""") ~ delete _;
StreamWriter khrDfWriter = new .()..Create("../src/KHR_df.bf")..Write("""
// This file was generated by Cpp2Beef
using System;
using System.Interop;
namespace KTX;
""") ~ delete _;
protected override StreamWriter GetWriterForHeader(StringView header)
{
if (header.EndsWith("ktx.h"))
return ktxWriter;
if (header.EndsWith("ktxvulkan.h"))
return ktxVulkanWriter;
if (header.EndsWith("khr_df.h"))
return khrDfWriter;
return null;
}
Dictionary<String, CXType> vtblPfns = new .(24) ~ DeleteDictionaryAndKeys!(_);
protected override void HandleCursor(CXCursor cursor)
{
switch (cursor.kind)
{
case .TypedefDecl:
let spelling = GetCursorSpelling!(cursor);
if (spelling == "ktxHashList" || spelling == "ktxHashListEntry" || spelling == "ktxStream")
return;
case .MacroDefinition:
let spelling = GetCursorSpelling!(cursor);
if (spelling == "KTXTEXTURECLASSDEFN" || spelling == "KTX_APIENTRYP" || spelling == "KTX_API" ||
spelling == "KTX_APIENTRY" || spelling == "KTX_error_code")
return;
if (Clang.Cursor_IsMacroFunctionLike(cursor) == 0 || !spelling.StartsWith("ktx")) break;
BeginCursor(cursor);
AccessSpecifier(cursor);
str.Append("static ");
let nameInBindings = spelling[(spelling.IndexOf('_')+1)...];
Runtime.Assert(vtblPfns.TryGetAlt(nameInBindings, ?, let pfnType));
Type(Clang.GetResultType(pfnType));
str.Append(' ');
str.Append(nameInBindings);
Flush();
let tokens = ScopeTokenize!(cursor, unit);
WriteTokens(tokens[1...], Clang.GetRangeEnd(Clang.Cursor_GetSpellingNameRange(cursor, 0, 0)), .Identifier);
String buffer = scope .(256)..Append(str);
uint32 argI = 0;
insert: for (int i = 0; i < buffer.Length; i++)
{
switch (buffer[i])
{
case '(', ',':
str.Clear();
Type(Clang.GetArgType(pfnType, argI++));
str.Append(' ');
int idx = i+1 + (_ == ',' ? 1 : 0);
buffer.Insert(idx, str);
case ')':
buffer.Insert(i+1, " =>");
break insert;
}
}
buffer.Replace("->", ".");
str.Set(buffer);
str.Append(';');
return;
case .StructDecl:
if (Clang.Cursor_IsAnonymous(cursor) != 0)
return;
if (Clang.GetCursorLexicalParent(cursor).kind == .StructDecl)
return;
let spelling = GetCursorSpelling!(cursor);
if (spelling == "ktxKVListEntry" || (spelling == "ktxStream" && Clang.EqualCursors(cursor, Clang.GetTypeDeclaration(Clang.GetCursorType(cursor))) != 0))
return;
BeginCursor(cursor);
Record(cursor);
return;
case .FieldDecl:
if (GetCursorSpelling!(Clang.GetCursorSemanticParent(cursor)) == "ktxTexture_vtbl")
vtblPfns.Add(new .(GetCursorSpelling!(cursor)),
Clang.GetPointeeType(Clang.GetTypedefDeclUnderlyingType(Clang.GetTypeDeclaration(Clang.GetCursorType(cursor))))
);
default:
}
base.HandleCursor(cursor);
if (fileInfo.prevEnd == default)
fileInfo.prevEnd = GetCursorAnchor(cursor);
}
append String blockBuffer;
protected override Block GetCursorBlock(CXCursor cursor)
{
if (cursor.kind == .FunctionDecl || cursor.kind == .MacroDefinition) do
{
let spelling = GetCursorSpelling!(cursor);
if (!spelling.StartsWith("ktx")) break;
int index = spelling.IndexOf('_');
if (index < 0) break;
blockBuffer.Set(spelling[..<index]);
return .CustomBlock(blockBuffer);
}
return base.GetCursorBlock(cursor);
}
protected override void WriteCustomAttributes(CXCursor cursor)
{
if (cursor.kind == .FunctionDecl || (cursor.kind == .TypedefDecl &&
{
let type = Clang.GetTypedefDeclUnderlyingType(cursor);
let pointee = Clang.GetPointeeType(type).kind;
type.kind == .Pointer && (pointee == .FunctionNoProto || pointee == .FunctionProto)
}))
{
str.Append("[CallingConvention(KTX_APIENTRYP)] ");
}
base.WriteCustomAttributes(cursor);
}
protected override void WriteTokensAfterEquals(CXCursor cursor)
{
if (cursor.kind == .ParmDecl)
return; // avoid clang compiler bug
base.WriteTokensAfterEquals(cursor);
}
protected override void WriteToken(CXToken token)
{
if (currentCursor.kind == .MacroDefinition)
{
let cursorSpelling = GetCursorSpelling!(currentCursor);
if (Clang.GetTokenKind(token) == .Punctuation && cursorSpelling == "KTX_IDENTIFIER_REF")
switch (GetTokenSpelling!(token))
{
case "{": str.Append("uint8[?]("); return;
case "}": str.Append(')'); return;
}
else if (cursorSpelling == "KTX_TRUE" || cursorSpelling == "KTX_FALSE")
{
str.Append(GetTokenSpelling!(token));
return;
}
else if (cursorSpelling == "KTX_FACESLICE_WHOLE_LEVEL")
{
str.Append("uint32.MaxValue");
return;
}
}
base.WriteToken(token);
}
protected override void Type(CXType type, TypeParamMode paramMode = .None)
{
if (currentCursor.kind == .TypedefDecl && Clang.EqualTypes(Clang.GetCursorType(currentCursor), type) != 0 && GetTypeSpelling!(type) == "ktx_uint32_t")
{
let cursorSpelling = GetCursorSpelling!(currentCursor);
str.Append(cursorSpelling);
if (cursorSpelling.EndsWith("_flags"))
{
str.Length--;
str.Append("_bits");
}
str.Append("_e");
return;
}
base.Type(type, paramMode);
}
protected override void GetNameInBindings(CXCursor cursor, String outString)
{
switch (cursor.kind)
{
case .EnumDecl:
var spelling = GetCursorSpelling!(cursor);
if (spelling.StartsWith("_khr"))
spelling.RemoveFromStart(1);
outString.Append(spelling);
return;
case .EnumConstantDecl:
var parent = GetCursorSpelling!(Clang.GetCursorSemanticParent(cursor));
if (parent == "ktx_error_code_e") break;
if (parent == "_khr_word_e")
parent = "khr_df_word_e";
var spelling = GetCursorSpelling!(cursor);
if (parent == "_khr_df_model_channels_e")
{
spelling.RemoveFromStart("KHR_DF_CHANNEL_".Length);
outString.Append(spelling);
return;
}
if (parent == "ktxSupercmpScheme")
{
spelling.RemoveFromStart("KTX_SS_".Length);
UpperSnakeCase2PascalCase(spelling, outString);
return;
}
if (parent == "ktxTextureCreateStorageEnum")
{
spelling.RemoveFromStart("KTX_TEXTURE_CREATE_".Length);
UpperSnakeCase2PascalCase(spelling, outString);
return;
}
if (parent == "ktxTextureCreateFlagBits")
{
spelling.RemoveFromStart("KTX_TEXTURE_CREATE_".Length);
if (spelling.EndsWith("_BIT"))
spelling.RemoveFromEnd(4);
UpperSnakeCase2PascalCase(spelling, outString);
return;
}
for (var part in parent.Split('_', .RemoveEmptyEntries))
{
if (part == "e") break;
part.Length++;
if (!spelling.StartsWith(part, .OrdinalIgnoreCase))
{
if (part.EndsWith("s_") && spelling.StartsWith(part[..<^2], .OrdinalIgnoreCase))
part.Length--;
else
break;
}
spelling.RemoveFromStart(part.Length);
}
if (spelling[0].IsDigit)
outString.Append('_');
UpperSnakeCase2PascalCase(spelling, outString);
return;
case .FunctionDecl:
let spelling = GetCursorSpelling!(cursor);
int index = spelling.IndexOf('_');
if (index < 0) break;
outString.Append(spelling[(index+1)...]);
return;
default:
}
base.GetNameInBindings(cursor, outString);
}
}
class Program
{
[CLink] static extern int32 system(char8*);
public static int Main(String[] args)
{
if (system("git -C .. submodule init") != 0)
Runtime.FatalError("Failed to fetch KTX-Software");
/*if (system(scope $"wget -O include/KHR/khr_df.h https://registry.khronos.org/DataFormat/api/1.3/khr_df.h") != 0)
Runtime.FatalError("Failed to download khr_df.h");
if (system(scope $"wget -O include/vulkan_core.h https://raw.githubusercontent.com/KhronosGroup/Vulkan-Headers/refs/heads/main/include/vulkan/vulkan_core.h") != 0)
Runtime.FatalError("Failed to download vulkan_core.h");
if (system(scope $"wget -O include/vk_platform.h https://raw.githubusercontent.com/KhronosGroup/Vulkan-Headers/refs/heads/main/include/vulkan/vk_platform.h") != 0)
Runtime.FatalError("Failed to download vk_platform.h");*/
scope ExampleGenerator(char8*[?]("--language=c", "-I../KTX-Software/lib/include", "-I../KTX-Software/external/dfdutils", "-DKTX_DOXYGEN_SKIP")).Generate("include/all.h");
return 0;
}
}