aboutsummaryrefslogtreecommitdiffstatsci
diff options
context:
space:
mode:
authorJean-Philippe Bruyère <jp_bruyere@hotmail.com>2021-12-02 08:35:09 +0100
committerJean-Philippe Bruyère <jp_bruyere@hotmail.com>2021-12-02 08:35:09 +0100
commit7c27042d45798225306dfbc677640ea2701f8e1a (patch)
treee802c4333b8aada3db4d2f88dc23e5aec2910553
parent4a39db4c1d61907188a411d4db73033f77fc4813 (diff)
some docs, build dependecies, netcoreapp3.1 for tools and test
-rw-r--r--VK/vulkan.csproj66
-rw-r--r--tests/Program.cs34
-rw-r--r--tests/tests.csproj11
-rw-r--r--vk.generator/Program.cs261
-rw-r--r--vk.net.sln13
-rw-r--r--vulkan/ExtensionMethods.cs98
-rw-r--r--vulkan/PinnedObjects.cs21
-rw-r--r--vulkan/Utils.cs6
-rw-r--r--vulkan/vulkan.csproj10
9 files changed, 429 insertions, 91 deletions
diff --git a/VK/vulkan.csproj b/VK/vulkan.csproj
deleted file mode 100644
index 2d52f03..0000000
--- a/VK/vulkan.csproj
+++ /dev/null
@@ -1,66 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<Project Sdk="Microsoft.NET.Sdk">
- <PropertyGroup>
- <TargetFrameworks>netstandard2.0</TargetFrameworks>
-
- <AssemblyVersion>0.2.4</AssemblyVersion>
- <AssemblyName>VK</AssemblyName>
- <Description>Low level vulkan bindings for .net</Description>
- <Product>VK</Product>
- <PackageLicence>MIT</PackageLicence>
- <PackageId>Vulkan</PackageId>
- <PackageTags>C# vulkan net binding</PackageTags>
- <PackageLicenseExpression>MIT</PackageLicenseExpression>
- <PackageVersion>$(AssemblyVersion)</PackageVersion>
- <GeneratePackageOnBuild>True</GeneratePackageOnBuild>
- <PackageProjectUrl>https://github.com/jpbruyere/vk.net/blob/master/README.md</PackageProjectUrl>
- <Icon>vk.net-64.png</Icon>
- <PackageIcon>vk.net-64.png</PackageIcon>
- <SynchReleaseVersion>false</SynchReleaseVersion>
- <PackageReleaseNotes>
-
- </PackageReleaseNotes>
- </PropertyGroup>
-
- <ItemGroup>
- <Content Include="vk.net-64.png" Pack="true" PackagePath="" />
- <ProjectReference Include="../vk.generator/vk.generator.csproj">
- <ReferenceOutputAssembly>false</ReferenceOutputAssembly>
- </ProjectReference>
- <ProjectReference Include="../vk.rewrite/vk.rewrite.csproj">
- <ReferenceOutputAssembly>false</ReferenceOutputAssembly>
- </ProjectReference>
- </ItemGroup>
-
- <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
- <AllowUnsafeBlocks>true</AllowUnsafeBlocks>
- <DefineConstants>TRACE;NETSTANDARD;NETSTANDARD2_0;DEBUG</DefineConstants>
- </PropertyGroup>
- <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
- <AllowUnsafeBlocks>true</AllowUnsafeBlocks>
- <DefineConstants>NETSTANDARD;NETSTANDARD2_0</DefineConstants>
- </PropertyGroup>
-
- <Target Name="generate" BeforeTargets="BeforeCompile">
- <MakeDir Directories="$(SolutionDir)build/generated" />
- <Exec Condition="$(OS) == 'Windows_NT'" Command="$(SolutionDir)build/$(Configuration)/$(ToolsFramework)/vk.generator.exe" WorkingDirectory="$(SolutionDir)build/generated">
- <Output TaskParameter="ConsoleOutput" PropertyName="OutputOfExec" />
- </Exec>
- <Exec Condition="$(OS) != 'Windows_NT'" Command="mono $(SolutionDir)build/$(Configuration)/$(ToolsFramework)/vk.generator.exe" WorkingDirectory="$(SolutionDir)build/generated">
- <Output TaskParameter="ConsoleOutput" PropertyName="OutputOfExec" />
- </Exec>
- <CreateItem Include="$(SolutionDir)build/generated/*.cs">
- <Output TaskParameter="Include" ItemName="Compile" />
- </CreateItem>
- </Target>
-
- <Target Name="rewrite" AfterTargets="CoreBuild">
- <Exec Condition="$(OS) == 'Windows_NT'" Command="$(SolutionDir)build/$(Configuration)/$(ToolsFramework)/vk.rewrite.exe $(TargetPath)" ConsoleToMSBuild="true" EchoOff="true">
- <Output TaskParameter="ConsoleOutput" PropertyName="OutputOfExec" />
- </Exec>
- <Exec Condition="$(OS) != 'Windows_NT'" Command="mono $(SolutionDir)build/$(Configuration)/$(ToolsFramework)/vk.rewrite.exe $(TargetPath)" ConsoleToMSBuild="true" EchoOff="true">
- <Output TaskParameter="ConsoleOutput" PropertyName="OutputOfExec" />
- </Exec>
- </Target>
-
-</Project>
diff --git a/tests/Program.cs b/tests/Program.cs
new file mode 100644
index 0000000..dcbdd2a
--- /dev/null
+++ b/tests/Program.cs
@@ -0,0 +1,34 @@
+using System;
+using Vulkan;
+using static Vulkan.Vk;
+using Version = Vulkan.Version;
+
+namespace tests
+{
+ class Program
+ {
+ static void Main(string[] args)
+ {
+ VkInstance instance;
+
+ VkInstanceCreateInfo ci = VkInstanceCreateInfo.New();
+ VkApplicationInfo ai = VkApplicationInfo.New();
+ //ai.apiVersion = new Version (1,0,0);
+ //ai.applicationVersion = new Version (1,0,0);
+
+ using (PinnedObjects pi = new PinnedObjects()) {
+ ci.pApplicationInfo = ai.Pin(pi);
+
+ VkResult res = vkCreateInstance (ref ci, IntPtr.Zero, out instance);
+ if (res != VkResult.Success) {
+ Console.WriteLine ($"Error: {res}");
+ return;
+ }else
+ Console.WriteLine ($"Success: {res}");
+
+ }
+
+ vkDestroyInstance (instance, IntPtr.Zero);
+ }
+ }
+}
diff --git a/tests/tests.csproj b/tests/tests.csproj
new file mode 100644
index 0000000..ed261c9
--- /dev/null
+++ b/tests/tests.csproj
@@ -0,0 +1,11 @@
+<Project Sdk="Microsoft.NET.Sdk">
+
+ <PropertyGroup>
+ <OutputType>Exe</OutputType>
+ <TargetFramework>netcoreapp3.1</TargetFramework>
+ </PropertyGroup>
+
+ <ItemGroup>
+ <ProjectReference Include="..\vulkan\vulkan.csproj" />
+ </ItemGroup>
+</Project>
diff --git a/vk.generator/Program.cs b/vk.generator/Program.cs
index 2cc3094..a7c5419 100644
--- a/vk.generator/Program.cs
+++ b/vk.generator/Program.cs
@@ -9,6 +9,7 @@ using System.IO;
using System.Xml;
using System.Linq;
using System.Net;
+using System.Text.RegularExpressions;
namespace vk.generator {
@@ -145,7 +146,7 @@ namespace vk.generator {
{ "xcb_visualid_t", "Xcb.xcb_visualid_t" },
//those are not checked, just putted there for compiling
- { "GgpFrameToken", "uint" }, //cant find header to check length
+ { "GgpFrameToken", "uint" }, //cant find header to check length
{ "zx_handle_t", "ulong" },
{ "GgpStreamDescriptor", "ulong" },
{ "PFN_vkVoidFunction","IntPtr" },
@@ -195,7 +196,7 @@ namespace vk.generator {
"vkEnumerateInstanceLayerProperties",
"vkEnumerateInstanceVersion"};
- static string[] reservedNames = { "event", "object" };
+ static string[] reservedNames = { "event", "object" };
static Dictionary<string, ParamDef> paramsDefs = new Dictionary<string, ParamDef> ();
@@ -320,11 +321,11 @@ namespace vk.generator {
return name == other.name;
}
public override bool Equals(object obj){
- if(obj == null) return false;
+ if(obj == null) return false;
return name == (obj as EnumerantValue).name;
}
public override int GetHashCode(){
- return value.GetHashCode();
+ return value.GetHashCode();
}
}
@@ -400,6 +401,10 @@ namespace vk.generator {
}
static string[] valueTypes = { "byte", "int", "uint", "float", "ushort", "ulong" };
static void gen_struct (IndentedTextWriter tw, StructDef sd) {
+ bool hasDoc = tryFindRefPage (sd.Name, out refPage rp);
+ if (hasDoc)
+ rp.writeSummaryAndRemarks (tw);
+
if (sd.category == TypeCategories.union)
tw.WriteLine($"[StructLayout(LayoutKind.Explicit)]");
else
@@ -407,7 +412,9 @@ namespace vk.generator {
tw.WriteLine ($"public unsafe partial struct {sd.Name} {{");
tw.Indent++;
foreach (MemberDef mb in sd.members) {
- if (!string.IsNullOrEmpty (mb.comment))
+ if (hasDoc)
+ rp.writeMemberDocIfFound (tw, mb.Name);
+ else if (!string.IsNullOrEmpty (mb.comment))
tw.WriteLine ($"/// <summary> {mb.comment} </summary>");
string typeStr;
@@ -532,8 +539,10 @@ namespace vk.generator {
tw.WriteLine (@"}");
}
- static void gen_enum_value (IndentedTextWriter tw, string enumName, EnumerantValue ev) {
- if (!string.IsNullOrEmpty (ev.comment))
+ static void gen_enum_value (IndentedTextWriter tw, string enumName, EnumerantValue ev, refPage? refpage = null) {
+ if (refpage.HasValue)
+ refpage.Value.writeMemberDocIfFound (tw, ev.Name);
+ else if (!string.IsNullOrEmpty (ev.comment))
tw.WriteLine ($"/// <summary> {ev.comment} </summary>");
if (!string.IsNullOrEmpty (ev.unusedComment))
tw.WriteLine ($"[Obsolete(\"{ev.unusedComment}\"]");
@@ -569,9 +578,11 @@ namespace vk.generator {
AddAlias (ed.Name, "uint");
continue;
}
-
- if (!string.IsNullOrEmpty (ed?.comment))
- tw.WriteLine ($"/// <summary> {ed.comment} </summary>");
+ bool hasDoc = tryFindRefPage (ed.Name, out refPage rp);
+ if (hasDoc) {
+ rp.writeSummaryAndRemarks (tw);
+ } else if (!string.IsNullOrEmpty (ed?.comment))
+ tw.WriteLine ($"///<summary>{ed.comment}</summary>");
if (ed?.type == EnumTypes.bitmask) {
tw.WriteLine (@"[Flags]");
tw.WriteLine ($"public enum {td.CSName} : uint {{");
@@ -580,12 +591,20 @@ namespace vk.generator {
tw.Indent++;
- foreach (EnumerantValue ev in ed.values.OrderBy(aa => aa.isAlias))
- gen_enum_value (tw, td.CSName, ev);
+ foreach (EnumerantValue ev in ed.values.OrderBy(aa => aa.isAlias)) {
+ if (hasDoc)
+ gen_enum_value (tw, td.CSName, ev, rp);
+ else
+ gen_enum_value (tw, td.CSName, ev);
+ }
IEnumerable<EnumerantValue> ext = extends.Where (e => e.extends == ed.Name);
- foreach (EnumerantValue ev in ext.OrderBy(aa => aa.isAlias))
- gen_enum_value (tw, td.CSName, ev);
+ foreach (EnumerantValue ev in ext.OrderBy(aa => aa.isAlias)) {
+ if (hasDoc)
+ gen_enum_value (tw, td.CSName, ev, rp);
+ else
+ gen_enum_value (tw, td.CSName, ev);
+ }
tw.Indent--;
@@ -645,6 +664,8 @@ namespace vk.generator {
}
}
static void gen_handle (IndentedTextWriter tw, HandleDef hd) {
+ if (tryFindRefPage (hd.Name, out refPage rp))
+ rp.writeSummaryAndRemarks(tw, true);
tw.WriteLine (@"[DebuggerDisplay(""{DebuggerDisplay,nq}"")]");
tw.WriteLine ($"public struct {hd.CSName} : IEquatable<{hd.CSName}>");
tw.WriteLine (@"{");
@@ -791,9 +812,15 @@ namespace vk.generator {
}
}
}
-
- foreach (string sig in signatures)
- writeCmd (tw, string.Format ($"{cd.returnType.CSName} {cd.Name} ({sig}"));
+ if (tryFindRefPage (cd.Name, out refPage rp)) {
+ foreach (string sig in signatures) {
+ rp.writeSummaryAndRemarks(tw);
+ writeCmd (tw, string.Format ($"{cd.returnType.CSName} {cd.Name} ({sig}"));
+ }
+ } else {
+ foreach (string sig in signatures)
+ writeCmd (tw, string.Format ($"{cd.returnType.CSName} {cd.Name} ({sig}"));
+ }
tw.WriteLine ();
}
@@ -1255,7 +1282,200 @@ namespace vk.generator {
}
#endregion
- const string vkxmlLocal = "Vulkan-Docs/xml/vk.xml";
+ /// <summary>
+ /// this is a summary #ref:string
+ /// </summary>
+ struct refPage {
+ public string bief;
+ public string description;
+ public string cspecInfos;
+ public Dictionary<string, string> members;
+
+ public void writeSummaryAndRemarks (IndentedTextWriter tw, bool writecspecAsRemark = false) {
+ tw.WriteLine ($"///<summary>{bief}</summary>");
+ if (description != null || (writecspecAsRemark && cspecInfos != null)) {
+ tw.WriteLine ($"///<remarks>");
+ if (writecspecAsRemark) {
+ foreach (string s in splitLines (cspecInfos))
+ tw.WriteLine ($"///{s}");
+ }
+ foreach (string s in splitLines (description))
+ tw.WriteLine ($"///{s}");
+ tw.WriteLine ($"///</remarks>");
+ }
+ }
+ public void writeMemberDocIfFound (IndentedTextWriter tw, string memberName) {
+ if (members == null || !members.ContainsKey (memberName))
+ return;
+ string[] docs = splitLines (members[memberName]).ToArray();
+ if (docs.Length == 1)
+ tw.WriteLine ($"///<summary>{docs[0]}</summary>");
+ else {
+ tw.WriteLine ($"///<summary>");
+ foreach (string d in docs)
+ tw.WriteLine ($"///{d}");
+ tw.WriteLine ($"///</summary>");
+ }
+ }
+ }
+ static IEnumerable<string> splitLines (string s) {
+ if (string.IsNullOrEmpty (s))
+ return new List<string>();
+ List<string> tmp = s.Split (@"\n").ToList();
+ int start = tmp.FindIndex (0, tmp.Count, l=>!string.IsNullOrEmpty(l));
+ if (start<0)
+ return new List<string>();
+ int end = tmp.Count < 2 ? tmp.Count - 1 :
+ tmp.FindLastIndex (tmp.Count - 1, start, l=>!string.IsNullOrEmpty(l));
+ if (end < 0)
+ return tmp.GetRange (start, tmp.Count - start);
+ else
+ return tmp.GetRange (start, end + 1 - start);
+ }
+ static Regex linkRx = new Regex (@"[p|f|s|e]link:([a-zA-Z0-9_:]*)", RegexOptions.Multiline);
+ static Regex nameRx = new Regex (@"([p|f|s|e]name|code):([a-zA-Z0-9_]*)", RegexOptions.Multiline);
+ //static Regex elinkRx = new Regex (@"[p|f|s|e]link:([a-zA-Z0-9]*)", RegexOptions.Multiline);
+ static string seecrefG1replace = @"<see cref=""$1""/>";
+ static string codeG2replace = @"<c>$2</c>";
+ static string docReplacements (string s) {
+ if (string.IsNullOrEmpty (s))
+ return "";
+ string tmp = linkRx.Replace(s, seecrefG1replace);
+ tmp = tmp.Replace ("::pname:", ".");
+ tmp = nameRx.Replace(tmp, codeG2replace);
+
+ return tmp;
+ }
+ static string readRefPageMembers (StreamReader sr, ref refPage refpage, bool isEnum) {
+ refpage.members = new Dictionary<string, string>();
+ string memberName = null;
+ string memberDoc = null;
+ Stack<string> conditionsStack = new Stack<string>();
+ while (!sr.EndOfStream) {
+ string l = sr.ReadLine().Trim();
+ if (l.StartsWith ("include::{generated}/api"))
+ continue;
+
+ if (l.StartsWith ("ifdef::")) {
+ conditionsStack.Push (l);
+ continue;
+ }
+ if (l.StartsWith ("endif::")) {
+ if (!conditionsStack.TryPop (out string condition)) {
+ printError ($"empty condition stack: {l}");
+ }
+ }
+ if (l.StartsWith ("== ") || l.StartsWith (".")) {
+ if (memberName != null) {
+ if (refpage.members.ContainsKey (memberName))
+ refpage.members[memberName] += @"\n--duplicated--\n" + docReplacements (memberDoc);
+ else
+ refpage.members.Add (memberName, docReplacements (memberDoc));
+ }
+ return l;
+ }
+ if (isEnum && string.IsNullOrEmpty(l)) {
+ if (memberName != null) {
+ refpage.members.Add (memberName, docReplacements (memberDoc));
+ return l;
+ }
+ continue;
+ }
+ if (l.StartsWith ("* ename:") || l.StartsWith ("* pname:")) {
+ l = l.Substring (8);
+ int nameEndIdx = l.IndexOf (' ');
+ string newMemberName = nameEndIdx < 0 ? l : l.Substring (0,nameEndIdx);
+ string newMemberDoc = nameEndIdx < 0 ? "" : l.Substring (nameEndIdx + 1);
+
+ if (memberName != null) {
+ if (newMemberName == memberName) {
+ memberDoc += @"\n" + newMemberDoc;
+ continue;
+ }
+ if (refpage.members.ContainsKey (memberName))
+ refpage.members[memberName] += @"\n--duplicated--\n" + docReplacements (memberDoc);
+ else
+ refpage.members.Add (memberName, docReplacements (memberDoc));
+ }
+ memberName = newMemberName;
+ memberDoc = newMemberDoc;
+ continue;
+ }
+ memberDoc += @"\n" + l;
+ }
+ return null;
+ }
+ static bool tryFindRefPage (string name, out refPage refpage) {
+ refpage = default;
+ string path = Path.Combine (vkrefsdir, $"{name}.txt");
+ if (!File.Exists(path))
+ return false;
+ bool isEnum = true;
+
+ using (StreamReader sr = new StreamReader (path)) {
+ string l = null, savedLine = null;
+ while(!sr.EndOfStream) {
+ if (savedLine != null) {
+ l = savedLine;
+ savedLine = null;
+ } else
+ l = sr.ReadLine();
+ if (l.StartsWith ("= ")) {
+ int idx = l.IndexOf ('(');
+ if (idx < 1 || l.Substring (2, idx - 2) != name)
+ Debugger.Break();
+ continue;
+ }
+ if (l.StartsWith ("== Name")) {
+ l = sr.ReadLine();
+ refpage.bief = l.Substring (name.Length + 3);
+ continue;
+ }
+ if (l.StartsWith ("== C Specification")) {
+ while (!sr.EndOfStream) {
+ l = sr.ReadLine();
+ if (l.StartsWith ("include::{generated}/api"))
+ continue;
+ if (l.StartsWith ("== ") || l.StartsWith (".")) {
+ savedLine = l;
+ break;
+ }
+ if (!string.IsNullOrEmpty(refpage.cspecInfos))
+ refpage.cspecInfos += @"\n";
+ refpage.cspecInfos += docReplacements (l);
+ }
+ continue;
+ }
+ if (l.StartsWith ("== Members") || l.StartsWith ("== Parameters")) {
+ isEnum = false;
+ savedLine = readRefPageMembers (sr, ref refpage, isEnum);
+ continue;
+ }
+ if (l.StartsWith ("== Description")) {
+ if (isEnum) {
+ savedLine = readRefPageMembers (sr, ref refpage, isEnum);
+ if (savedLine != null)
+ continue;
+ }
+ while (!sr.EndOfStream) {
+ l = sr.ReadLine();
+ if (l.StartsWith ("include::{generated}/api"))
+ continue;
+ if (l.StartsWith ("== ") || l.StartsWith (".")) {
+ savedLine = l;
+ break;
+ }
+ if (!string.IsNullOrEmpty(refpage.description))
+ refpage.description += @"\n";
+ refpage.description += docReplacements (l);
+ }
+ continue;
+ }
+ }
+ }
+ return true;
+ }
+ const string vkrefsdir = "Vulkan-Docs/gen/refpage";
const string targetDir = "build/generated";
static string targetPath (string fileName) =>
Path.Combine (targetDir, $"{fileName}_gen.cs");
@@ -1267,6 +1487,11 @@ namespace vk.generator {
}
public static void Main (string[] args) {
+ if(args.Length < 1) {
+ Console.WriteLine ("Usage: vk.generator path/to/vk.xml");
+ return;
+ }
+ string vkxmlLocal = args[0];
if (!File.Exists(vkxmlLocal)) {
printError ($"[GEN] {Path.Combine (Directory.GetCurrentDirectory(),vkxmlLocal)} not found.");
diff --git a/vk.net.sln b/vk.net.sln
index 62cfa5f..4636a48 100644
--- a/vk.net.sln
+++ b/vk.net.sln
@@ -1,15 +1,20 @@
-Microsoft Visual Studio Solution File, Format Version 12.00
+Microsoft Visual Studio Solution File, Format Version 12.00
# Visual Studio 15
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "vk.generator", "vk.generator\vk.generator.csproj", "{B105512C-9461-4802-B299-A6E7A29CDAEE}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "vulkan", "vulkan\vulkan.csproj", "{37D01BE5-5FE2-4742-BD5B-5D2C25FCF146}"
ProjectSection(ProjectDependencies) = postProject
- {B105512C-9461-4802-B299-A6E7A29CDAEE} = {AB8DF076-E252-4FDF-BCD4-9503851BB9A0}
+ {B105512C-9461-4802-B299-A6E7A29CDAEE} = {B105512C-9461-4802-B299-A6E7A29CDAEE}
{5EC0F6C6-74C9-4509-8AC8-FAE3574AF5C7} = {5EC0F6C6-74C9-4509-8AC8-FAE3574AF5C7}
EndProjectSection
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "vk.rewrite", "vk.rewrite\vk.rewrite.csproj", "{5EC0F6C6-74C9-4509-8AC8-FAE3574AF5C7}"
EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "tests", "tests\tests.csproj", "{6EA93907-C477-45D7-BB68-50940821B1F1}"
+ ProjectSection(ProjectDependencies) = postProject
+ {37D01BE5-5FE2-4742-BD5B-5D2C25FCF146} = {37D01BE5-5FE2-4742-BD5B-5D2C25FCF146}
+ EndProjectSection
+EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
@@ -28,6 +33,10 @@ Global
{5EC0F6C6-74C9-4509-8AC8-FAE3574AF5C7}.Debug|Any CPU.Build.0 = Debug|Any CPU
{5EC0F6C6-74C9-4509-8AC8-FAE3574AF5C7}.Release|Any CPU.ActiveCfg = Release|Any CPU
{5EC0F6C6-74C9-4509-8AC8-FAE3574AF5C7}.Release|Any CPU.Build.0 = Release|Any CPU
+ {6EA93907-C477-45D7-BB68-50940821B1F1}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {6EA93907-C477-45D7-BB68-50940821B1F1}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {6EA93907-C477-45D7-BB68-50940821B1F1}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {6EA93907-C477-45D7-BB68-50940821B1F1}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(NestedProjects) = preSolution
EndGlobalSection
diff --git a/vulkan/ExtensionMethods.cs b/vulkan/ExtensionMethods.cs
new file mode 100644
index 0000000..0b9797f
--- /dev/null
+++ b/vulkan/ExtensionMethods.cs
@@ -0,0 +1,98 @@
+// Copyright (c) 2019 Jean-Philippe Bruyère <jp_bruyere@hotmail.com>
+//
+// This code is licensed under the MIT license (MIT) (http://opensource.org/licenses/MIT)
+using System;
+using System.Collections.Generic;
+using System.Diagnostics;
+using System.Linq;
+using System.Runtime.InteropServices;
+
+using static Vulkan.Vk;
+
+namespace Vulkan {
+ public static class ExtensionMethods {
+ #region pinning
+ /// <summary>
+ /// list of pinned GCHandles used to pass value from managed to unmanaged code.
+ /// </summary>
+ public static Dictionary<object, GCHandle> handles = new Dictionary<object, GCHandle>();
+
+ /// <summary>
+ /// Unpin the specified object and free the GCHandle associated.
+ /// </summary>
+ public static void Unpin (this object obj) {
+ if (!handles.ContainsKey (obj)) {
+ Debug.WriteLine ("Trying to unpin unpinned object: {0}.", obj);
+ return;
+ }
+ handles[obj].Free ();
+ handles.Remove (obj);
+ }
+
+ /// <summary>
+ /// Pin the specified object and return a pointer. MUST be Unpined as soon as possible.
+ /// </summary>
+ public static IntPtr Pin (this object obj) {
+ if (handles.ContainsKey (obj)) {
+ Debug.WriteLine ("Trying to pin already pinned object: {0}", obj);
+ return handles[obj].AddrOfPinnedObject ();
+ }
+
+ GCHandle hnd = GCHandle.Alloc (obj, GCHandleType.Pinned);
+ handles.Add (obj, hnd);
+ return hnd.AddrOfPinnedObject ();
+ }
+ public static IntPtr Pin<T> (this List<T> obj) {
+ if (handles.ContainsKey (obj))
+ Debug.WriteLine ("Pinning already pinned object: {0}", obj);
+
+ GCHandle hnd = GCHandle.Alloc (obj.ToArray(), GCHandleType.Pinned);
+ handles.Add (obj, hnd);
+ return hnd.AddrOfPinnedObject ();
+ }
+ public static IntPtr Pin<T> (this T[] obj) {
+ if (handles.ContainsKey (obj))
+ Debug.WriteLine ("Pinning already pinned object: {0}", obj);
+
+ GCHandle hnd = GCHandle.Alloc (obj, GCHandleType.Pinned);
+ handles.Add (obj, hnd);
+ return hnd.AddrOfPinnedObject ();
+ }
+ public static IntPtr Pin (this string obj) {
+ if (handles.ContainsKey (obj)) {
+ Debug.WriteLine ("Trying to pin already pinned object: {0}", obj);
+ return handles[obj].AddrOfPinnedObject ();
+ }
+ byte[] n = System.Text.Encoding.UTF8.GetBytes(obj +'\0');
+ GCHandle hnd = GCHandle.Alloc (n, GCHandleType.Pinned);
+ handles.Add (obj, hnd);
+ return hnd.AddrOfPinnedObject ();
+ }
+
+ //pin with pinning context
+ public static IntPtr Pin (this object obj, PinnedObjects ctx) {
+ GCHandle hnd = GCHandle.Alloc (obj, GCHandleType.Pinned);
+ ctx.Handles.Add (hnd);
+ return hnd.AddrOfPinnedObject ();
+ }
+ public static IntPtr Pin<T> (this IList<T> obj, PinnedObjects ctx) {
+ GCHandle hnd = GCHandle.Alloc (obj.ToArray (), GCHandleType.Pinned);
+ ctx.Handles.Add (hnd);
+ return hnd.AddrOfPinnedObject ();
+ }
+ public static IntPtr Pin<T> (this T[] obj, PinnedObjects ctx) {
+ GCHandle hnd = GCHandle.Alloc (obj, GCHandleType.Pinned);
+ ctx.Handles.Add (hnd);
+ return hnd.AddrOfPinnedObject ();
+ }
+ public static IntPtr Pin (this string obj, PinnedObjects ctx) {
+ byte[] n = System.Text.Encoding.UTF8.GetBytes (obj + '\0');
+ GCHandle hnd = GCHandle.Alloc (n, GCHandleType.Pinned);
+ ctx.Handles.Add (hnd);
+ return hnd.AddrOfPinnedObject ();
+ }
+
+ #endregion
+
+ }
+}
diff --git a/vulkan/PinnedObjects.cs b/vulkan/PinnedObjects.cs
new file mode 100644
index 0000000..da14f26
--- /dev/null
+++ b/vulkan/PinnedObjects.cs
@@ -0,0 +1,21 @@
+// Copyright (c) 2019 Jean-Philippe Bruyère <jp_bruyere@hotmail.com>
+//
+// This code is licensed under the MIT license (MIT) (http://opensource.org/licenses/MIT)
+using System;
+using System.Collections.Generic;
+using System.Runtime.InteropServices;
+
+namespace Vulkan {
+ /// <summary>
+ /// Keep pinned object gc handles and free them on dispose.
+ /// </summary>
+ public class PinnedObjects : IDisposable {
+ public readonly List<GCHandle> Handles = new List<GCHandle> ();
+
+ public void Dispose () {
+ for (int i = Handles.Count - 1; i >= 0; i--)
+ Handles[i].Free ();
+ GC.SuppressFinalize (this);
+ }
+ }
+}
diff --git a/vulkan/Utils.cs b/vulkan/Utils.cs
index cd2b3ee..b91a47b 100644
--- a/vulkan/Utils.cs
+++ b/vulkan/Utils.cs
@@ -26,7 +26,7 @@ namespace Vulkan {
System.Diagnostics.Debug.WriteLine ("device function pointer not found for " + name);
else
ptr = del;
- hnd.Free ();
- }
- }
+ hnd.Free ();
+ }
+ }
}
diff --git a/vulkan/vulkan.csproj b/vulkan/vulkan.csproj
index 337aca0..a93dee5 100644
--- a/vulkan/vulkan.csproj
+++ b/vulkan/vulkan.csproj
@@ -22,21 +22,27 @@
</PackageReleaseNotes>
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
+ <GenerateDocumentationFile>true</GenerateDocumentationFile>
+
+
</PropertyGroup>
<ItemGroup>
<Content Include="vk.net-64.png" Pack="true" PackagePath="" />
</ItemGroup>
+ <ItemGroup>
+ <SpecFile Include="$(SolutionDir)Vulkan-Docs/xml/vk.xml" />
+ </ItemGroup>
<Target Name="generate" BeforeTargets="BeforeCompile">
<MakeDir Directories="$(SolutionDir)build/generated" />
<Exec Condition="$(OS) == 'Windows_NT'"
- Command="$(SolutionDir)vk.generator/bin/$(Configuration)/$(ToolsFramework)/vk.generator.exe"
+ Command="$(SolutionDir)vk.generator/bin/$(Configuration)/$(ToolsFramework)/vk.generator.exe %(SpecFile.Identity)"
WorkingDirectory="$(SolutionDir)">
<Output TaskParameter="ConsoleOutput" PropertyName="OutputOfExec" />
</Exec>
<Exec Condition="$(OS) != 'Windows_NT'"
- Command="$(SolutionDir)vk.generator/bin/$(Configuration)/$(ToolsFramework)/vk.generator"
+ Command="$(SolutionDir)vk.generator/bin/$(Configuration)/$(ToolsFramework)/vk.generator %(SpecFile.Identity)"
WorkingDirectory="$(SolutionDir)">
<Output TaskParameter="ConsoleOutput" PropertyName="OutputOfExec" />
</Exec>