public override void Run(TypeSet types, FileGenerator fileGenerator) { fileGenerator.Generate("Interop", "Commands", fileBuilder => { fileBuilder.EmitUsing("System"); fileBuilder.EmitUsing("System.Runtime.InteropServices"); fileBuilder.EmitNamespace("SharpVk.Interop", namespaceBuilder => { namespaceBuilder.EmitType(TypeKind.Class, "Commands", typeBuilder => { typeBuilder.EmitField("string", "VulkanDll", Public, Const, expr => expr.EmitLiteral("vulkan-1.dll")); foreach (var command in types.Commands) { typeBuilder.EmitMethod(command.ReturnTypeName, command.Name, null, paramsBuilder => { foreach (var param in command.Parameters) { paramsBuilder.EmitParam(param.TypeName, param.Name); } }, Public, Static | Extern, attributes: new[] { "DllImport(VulkanDll, CallingConvention = CallingConvention.Winapi)" }); } }, Public, modifiers: TypeModifier.Static | TypeModifier.Unsafe); }); }); }
public override void Run(TypeSet types, FileGenerator fileGenerator) { Parallel.ForEach(types.Enumerations, @enum => { fileGenerator.Generate(null, @enum.Name, builder => { builder.EmitUsing("System"); builder.EmitNamespace("SharpVk", namespaceBuilder => { var attributes = @enum.IsFlags ? new[] { "Flags" } : null; namespaceBuilder.EmitEnum(@enum.Name, enumBuilder => { foreach (var field in @enum.Fields) { enumBuilder.EmitField(field.Name, AsIs(field.Value), field.Comment); } }, Public, @enum.Comment, attributes: attributes); }); }); }); }
public override void Run(TypeSet types, FileGenerator fileGenerator) { fileGenerator.Generate("Interop", "Delegates", builder => { builder.EmitUsing("System"); builder.EmitNamespace("SharpVk.Interop", namespaceBuilder => { foreach (var @delegate in types.Delegates) { namespaceBuilder.EmitDelegate(@delegate.ReturnTypeName, @delegate.Name, Public, Unsafe, parameters => { foreach (var param in @delegate.Parameters) { parameters.EmitParam(param.TypeName, param.Name); } }, @delegate.Comment); } }); }); }
public override void Run(TypeSet types, FileGenerator fileGenerator) { var subGroups = types.Constants.Select(x => x.SubGroupName).Distinct(); fileGenerator.Generate(null, "Constants", fileBuilder => { fileBuilder.EmitNamespace("SharpVk", namespaceBuilder => { foreach (var subGroup in subGroups.Where(x => x != null)) { namespaceBuilder.EmitType(TypeKind.Class, subGroup, typeBuilder => { EmitConstantSubGroup(typeBuilder, types.Constants.Where(x => x.SubGroupName == subGroup)); }, Public, modifiers: TypeModifier.Static); } namespaceBuilder.EmitType(TypeKind.Class, "Constants", typeBuilder => { EmitConstantSubGroup(typeBuilder, types.Constants.Where(x => x.SubGroupName == null)); }, Public, modifiers: TypeModifier.Static | TypeModifier.Partial); }); }); }
public override void Run(TypeSet types, FileGenerator fileGenerator) { Parallel.ForEach(types.Handles, handle => { fileGenerator.Generate("Interop", handle.Name, fileBuilder => { fileBuilder.EmitUsing("System"); fileBuilder.EmitNamespace("SharpVk.Interop", namespaceBuilder => { namespaceBuilder.EmitType(TypeKind.Struct, handle.Name, typeBuilder => { const string handleFieldName = "handle"; string internalHandleType = handle.IsDispatch ? "UIntPtr" : "ulong"; typeBuilder.EmitField(internalHandleType, handleFieldName, Internal); typeBuilder.EmitConstructor(body => { body.EmitAssignment(Member(This, handleFieldName), Variable(handleFieldName)); }, parameters => { parameters.EmitParam(internalHandleType, handleFieldName); }, Public); typeBuilder.EmitProperty(handle.Name, "Null", Public, MemberModifier.Static, getBuilder => { getBuilder.EmitReturn(MemberInit(handle.Name, member => { member.EmitMember(handleFieldName, Default(internalHandleType)); })); }, summary: new[] { $"A read-only property that returns a null {handle.Name} handle." }); typeBuilder.EmitMethod("ulong", "ToUInt64", methodbody => { if (handle.IsDispatch) { methodbody.EmitReturn(Call(Member(This, "handle"), "ToUInt64")); } else { methodbody.EmitReturn(Member(This, "handle")); } }, null, Public, summary: new[] { "Returns the marshalled value of this handle as an unsigned 64-bit integer." }); }, Public, summary: handle.Comment); }); }); fileGenerator.Generate(null, handle.Name, fileBuilder => { fileBuilder.EmitUsing("System"); fileBuilder.EmitUsing("System.Runtime.InteropServices"); fileBuilder.EmitNamespace("SharpVk", namespaceBuilder => { var interfaces = new List <string>(); if (handle.IsDisposable) { interfaces.Add("IDisposable"); } if (handle.IsProcLookup) { interfaces.Add("IProcLookup"); } namespaceBuilder.EmitType(TypeKind.Class, handle.Name, typeBuilder => { string interopTypeName = "Interop." + handle.Name; typeBuilder.EmitField(interopTypeName, "handle", Internal, MemberModifier.Readonly); typeBuilder.EmitField("CommandCache", "commandCache", Internal, MemberModifier.Readonly); var parameters = new List <Action <ParameterBuilder> > { x => x.EmitParam(interopTypeName, "handle") }; var ctorStatements = new List <Action <CodeBlockBuilder> > { x => x.EmitAssignment(Member(This, "handle"), Variable("handle")) }; if (handle.ParentHandle != null) { typeBuilder.EmitField(handle.ParentHandle, "parent", methodModifers: MemberModifier.Readonly); typeBuilder.EmitProperty("AllocationCallbacks?", "Allocator", Internal, getter: getBuilder => { getBuilder.EmitReturn(Member(Member(This, "parent"), "Allocator")); }); parameters.Add(x => x.EmitParam(handle.ParentHandle, "parent")); ctorStatements.Add(x => x.EmitAssignment(Member(This, "parent"), Variable("parent"))); if (handle.AssociatedHandle != null) { typeBuilder.EmitField(handle.AssociatedHandle, "associated", methodModifers: MemberModifier.Readonly); parameters.Add(x => x.EmitParam(handle.AssociatedHandle, "associated")); ctorStatements.Add(x => x.EmitAssignment(Member(This, "associated"), Variable("associated"))); } } else { typeBuilder.EmitField("AllocationCallbacks?", "allocator", methodModifers: MemberModifier.Readonly); typeBuilder.EmitProperty("AllocationCallbacks?", "Allocator", Internal, getter: getBuilder => { getBuilder.EmitReturn(Member(This, "allocator")); }); parameters.Add(x => x.EmitParam("AllocationCallbacks?", "allocator")); ctorStatements.Add(x => x.EmitAssignment(Member(This, "allocator"), Variable("allocator"))); } var commandCacheAssignment = Variable("commandCache"); if (handle.IsProcLookup) { var parentCache = handle.ParentHandle != null ? Member(Variable("parent"), "commandCache") : Null; commandCacheAssignment = New("CommandCache", This, Literal(handle.ProcCacheType), parentCache); } else { parameters.Add(x => x.EmitParam("CommandCache", "commandCache")); } ctorStatements.Add(x => x.EmitAssignment(Member(This, "commandCache"), commandCacheAssignment)); typeBuilder.EmitConstructor(body => { foreach (var statement in ctorStatements) { statement(body); } }, paramsBuilder => { foreach (var param in parameters) { param(paramsBuilder); } }, Internal); foreach (var method in handle.Methods) { var methodModifiers = method.IsStatic ? MemberModifier.Static : MemberModifier.None; typeBuilder.EmitMethod(method.ReturnTypeName, method.Name, body => { body.EmitUnsafeBlock(unsafeBlock => { unsafeBlock.EmitTry(tryBlock => { Func <IEnumerable <Action <ExpressionBuilder> >, Action <ExpressionBuilder> > commandExpression = commandParameters => { return(StaticCall("Interop.Commands", method.CommandName, commandParameters.ToArray())); }; if (method.ShouldGetFromCache) { string delegateTypeName = "Interop." + method.CacheLookupName; tryBlock.EmitVariableDeclaration("var", "commandDelegate", Call(Member(This, "commandCache"), $"GetCommandDelegate<{delegateTypeName}>", Literal(method.CacheLookupName), Literal(method.CacheLookupType))); commandExpression = commandParameters => { return(DelegateCall(Variable("commandDelegate"), commandParameters.ToArray())); }; } if (method.ReturnTypeName != "void") { tryBlock.EmitVariableDeclaration(method.ReturnTypeName, "result", Default(method.ReturnTypeName)); } string commandResultVariable = "commandResult"; if (method.HasVkResult) { if (method.IsPassthroughResult) { commandResultVariable = "result"; } else { tryBlock.EmitVariableDeclaration("Result", "commandResult"); } } foreach (var statement in method.MarshalToStatements) { tryBlock.EmitStatement(statement); } if (method.IsDoubleInvoke) { EmitInvokeCommand(tryBlock, method, commandExpression, x => x.PreInvokeArgumentName ?? x.ArgumentName, commandResultVariable); foreach (var statement in method.MarshalMidStatements) { tryBlock.EmitStatement(statement); } } EmitInvokeCommand(tryBlock, method, commandExpression, x => x.ArgumentName, commandResultVariable); foreach (var statement in method.MarshalFromStatements) { tryBlock.EmitStatement(statement); } if (method.ReturnTypeName != "void") { tryBlock.EmitReturn(Variable("result")); } }, finallyBlock => finallyBlock.EmitStaticCall("Interop.HeapUtil", "FreeLog")); }); }, paramsBuilder => { foreach (var parameter in method.Parameters.Where(x => x.Name != null)) { paramsBuilder.EmitParam(parameter.TypeName, parameter.Name); } }, Public, methodModifiers, summary: method.Comment); } typeBuilder.EmitMethod("void", "MarshalTo", body => { body.EmitAssignment(Variable("*pointer"), Member(This, "handle")); }, paramsBuilder => { paramsBuilder.EmitParam(interopTypeName + "*", "pointer"); }, Internal, MemberModifier.Unsafe); typeBuilder.EmitProperty(interopTypeName, "RawHandle", Member(This, "handle"), Public, summary: new[] { $"The interop handle for this {handle.Name}." }); if (handle.IsDisposable) { typeBuilder.EmitMethod("void", "Dispose", body => { body.EmitCall(This, "Destroy"); }, null, Public, summary: new[] { "Releases the unmanaged resources associated with this instance and destroys the underlying Vulkan handle." }); } }, Public, interfaces, TypeModifier.Partial, summary: handle.Comment); }); }); }); }
public override void Run(TypeSet types, FileGenerator fileGenerator) { Parallel.ForEach(types.Structs, @struct => { fileGenerator.Generate(null, @struct.Name, builder => { builder.EmitUsing("System"); builder.EmitUsing("System.Runtime.InteropServices"); builder.EmitUsing("System.Text"); builder.EmitNamespace("SharpVk", namespaceBuilder => { namespaceBuilder.EmitType(TypeKind.Struct, @struct.Name, typeBuilder => { typeBuilder.EmitConstructor(body => { foreach (var member in @struct.Members) { string paramName = char.ToLower(member.Name[0]) + member.Name.Substring(1); body.EmitAssignment(Member(This, member.Name), Variable(paramName)); } }, parameters => { foreach (var member in @struct.Members) { string paramName = char.ToLower(member.Name[0]) + member.Name.Substring(1); parameters.EmitParam(member.TypeName, paramName); } }, Public); foreach (var member in @struct.Members) { typeBuilder.EmitField(member.TypeName, member.Name, member.IsPrivate ? Private : Public, summary: member.Comment); } typeBuilder.EmitMethod("string", "ToString", methodBody => { methodBody.EmitVariableDeclaration("var", "builder", New("StringBuilder")); methodBody.EmitCall(Variable("builder"), "AppendLine", Literal(@struct.Name)); methodBody.EmitCall(Variable("builder"), "AppendLine", Literal("{")); foreach (var member in @struct.Members) { methodBody.EmitCall(Variable("builder"), "AppendLine", Literal('$', $"{member.Name}: {{this.{member.Name}}}")); } methodBody.EmitCall(Variable("builder"), "Append", Literal("}")); methodBody.EmitReturn(Call(Variable("builder"), "ToString")); }, null, Public, Override); }, Public, modifiers: TypeModifier.Partial, attributes: new[] { "StructLayout(LayoutKind.Sequential)" }, summary: @struct.Comment); }); }); }); }
public override void Run(TypeSet types, FileGenerator fileGenerator) { Parallel.ForEach(types.InteropStructs, @struct => { fileGenerator.Generate("Interop", @struct.Name, builder => { builder.EmitUsing("System"); builder.EmitUsing("System.Runtime.InteropServices"); builder.EmitNamespace("SharpVk.Interop", namespaceBuilder => { namespaceBuilder.EmitType(TypeKind.Struct, @struct.Name, typeBuilder => { foreach (var member in @struct.Members) { typeBuilder.EmitField(member.TypeName, member.Name, member.IsPrivate ? Private : Public); } }, Public, modifiers: TypeModifier.Unsafe, attributes: new[] { "StructLayout(LayoutKind.Sequential)" }); }); }); }); Parallel.ForEach(types.Classes, @class => { fileGenerator.Generate(null, @class.Name, fileBuilder => { fileBuilder.EmitUsing("System"); fileBuilder.EmitNamespace("SharpVk", namespaceBuilder => { namespaceBuilder.EmitType(TypeKind.Struct, @class.Name, builder => { foreach (var member in @class.Properties) { builder.EmitProperty(member.TypeName, member.Name, Public, getter: Public, setter: Public, summary: member.Comment); } string interopTypeName = $"Interop.{@class.Name}"; string interopPointerName = interopTypeName + "*"; if ([email protected]) { builder.EmitMethod(interopPointerName, "MarshalTo", body => { body.EmitVariableDeclaration("var", "result", Cast(interopPointerName, Call(StaticCall("Interop.HeapUtil", $"AllocateAndClear<{interopTypeName}>"), "ToPointer"))); body.EmitCall(This, "MarshalTo", Variable("result")); body.EmitReturn(Variable("result")); }, null, Internal, Unsafe); builder.EmitMethod("void", "MarshalTo", body => { foreach (var statement in @class.MarshalToStatements) { body.EmitStatement(statement); } }, parameters => { parameters.EmitParam(interopPointerName, "pointer"); }, Internal, Unsafe); } else { builder.EmitMethod(@class.Name, "MarshalFrom", body => { const string resultVariableName = "result"; body.EmitVariableDeclaration(@class.Name, resultVariableName, New(@class.Name)); foreach (var statement in @class.MarshalFromStatements) { body.EmitStatement(statement); } body.EmitReturn(Variable(resultVariableName)); }, parameters => { parameters.EmitParam(interopPointerName, "value"); }, Internal, Static | Unsafe); } }, Public, summary: @class.Comment); }); }); }); }
public override void Run(TypeSet types, FileGenerator fileGenerator) { Parallel.ForEach(types.Unions, union => { fileGenerator.Generate(null, union.Name, builder => { builder.EmitUsing("System"); builder.EmitUsing("System.Runtime.InteropServices"); builder.EmitNamespace("SharpVk", namespaceBuilder => { namespaceBuilder.EmitType(TypeKind.Struct, union.Name, typeBuilder => { foreach (var member in union.Members) { string castType = member.TypeName; if (member.FixedSize > 0) { castType += "[]"; typeBuilder.EmitField(member.TypeName, member.Name, Private, Fixed, fixedLength: member.FixedSize, attributes: new[] { $"FieldOffset({member.FieldOffset})" }); } else { typeBuilder.EmitField(member.TypeName, member.Name, Private, attributes: new[] { $"FieldOffset({member.FieldOffset})" }); } typeBuilder.EmitMethod("operator", union.Name, methodBody => { if (member.FixedSize > 0) { methodBody.EmitVariableDeclaration(union.Name, "result", New(union.Name)); methodBody.EmitStaticCall("MemUtil", "WriteToPtr", New("IntPtr", Member(Variable("result"), member.Name)), Variable(member.Name), Literal(0), Literal(member.FixedSize)); methodBody.EmitReturn(Variable("result")); } else { methodBody.EmitReturn(MemberInit(union.Name, members => members.EmitMember(member.Name, Variable(member.Name)))); } }, parameters => parameters.EmitParam(castType, member.Name), Public, Static | Implicit, summary: new[] { $"Implicit conversion of {castType} to {union.Name}." }, docs: docs => docs.EmitParam(member.Name, member.Comment[0])); } }, Public, modifiers: TypeModifier.Unsafe | TypeModifier.Partial, attributes: new[] { "StructLayout(LayoutKind.Explicit)" }, summary: union.Comment); }); }); }); }
public override void Run(TypeSet types, FileGenerator fileGenerator) { fileGenerator.Generate(null, "Exceptions", builder => { builder.EmitUsing("System"); builder.EmitNamespace("SharpVk", namespaceBuilder => { namespaceBuilder.EmitType(TypeKind.Class, "SharpVkException", typeBuilder => { typeBuilder.EmitConstructor(methodBody => { }, parameters => parameters.EmitParam("string", "message"), Protected, baseArguments: new[] { Variable("message") }, summary: new[] { "Creates a new instance of the <see cref=\"SharpVk.SharpVkException\"/> class ." }, docs: docs => docs.EmitParam("message", "The message that describes the error.")); typeBuilder.EmitMethod("bool", "IsError", methodBody => methodBody.EmitReturn(LessThan(Cast("int", Variable("resultCode")), Literal(0))), parameters => parameters.EmitParam("Result", "resultCode"), Public, MemberModifier.Static, summary: new[] { "Returns a value indicating whether the given Vulkan result code represents an error." }); typeBuilder.EmitMethod("SharpVkException", "Create", methodBody => { methodBody.EmitIfBlock(Not(StaticCall("SharpVkException", "IsError", Variable("resultCode"))), ifBlock => ifBlock.EmitReturn(Null)); methodBody.EmitSwitchBlock(Variable("resultCode"), caseBuilder => { foreach (var exception in types.Exceptions) { caseBuilder.EmitCase(AsIs(exception.Value), caseBlock => caseBlock.EmitReturn(New(exception.Name))); } }); methodBody.EmitReturn(New("UnknownSharpVkException", Variable("resultCode"))); }, parameters => parameters.EmitParam("Result", "resultCode"), Public, MemberModifier.Static, summary: new[] { "Creates and returns a new, specifically-typed exception that represents the given result code." }); typeBuilder.EmitProperty("Result", "ResultCode", accessModifier: Public, methodModifers: MemberModifier.Abstract, getter: Public, summary: new[] { "The Vulkan result code represented by this exception." }); }, Public, new[] { "Exception" }, TypeModifier.Abstract, summary: new[] { "The base type for exceptions thrown by the SharpVK library." }); namespaceBuilder.EmitType(TypeKind.Class, "UnknownSharpVkException", typeBuilder => { typeBuilder.EmitField("Result", "resultCode"); typeBuilder.EmitConstructor(methodBody => { methodBody.EmitAssignment(Member(This, "resultCode"), Variable("resultCode")); }, parameters => parameters.EmitParam("Result", "resultCode"), Internal, baseArguments: new[] { AsIs("$\"An unknown exception as been thrown by the Vulkan API: {resultCode}\"") }); typeBuilder.EmitProperty("Result", "ResultCode", Member(This, "resultCode"), Public, MemberModifier.Override, new[] { "The Vulkan result code represented by this exception." }); }, Public, new[] { "SharpVkException" }, summary: new[] { "An exception representing a result code not recognised by the SharpVk library." }); foreach (var exception in types.Exceptions) { namespaceBuilder.EmitType(TypeKind.Class, exception.Name, typeBuilder => { string exceptionMessage = exception.Comment[0]; if (exceptionMessage == "-") { exceptionMessage = exception.Name; } typeBuilder.EmitConstructor(methodBody => { }, null, Internal, baseArguments: new[] { Literal(exceptionMessage) }); typeBuilder.EmitProperty("Result", "ResultCode", AsIs(exception.Value), Public, MemberModifier.Override, new[] { "The Vulkan result code represented by this exception." }); }, Public, new[] { "SharpVkException" }, summary: exception.Comment); } }); }); }