]> O.S.I.I.S - jp/vke.net.git/commitdiff
comments, move initVulkan in Run()
authorJean-Philippe Bruyère <jp_bruyere@hotmail.com>
Fri, 24 Jan 2020 23:57:07 +0000 (00:57 +0100)
committerJean-Philippe Bruyère <jp_bruyere@hotmail.com>
Fri, 24 Jan 2020 23:57:07 +0000 (00:57 +0100)
addons/Directory.Build.props
appveyor.yml [new file with mode: 0644]
samples/Directory.Build.props
vke.net.sln
vke/netfx.props [deleted symlink]
vke/src/VkWindow.cs
vke/src/base/Activable.cs
vke/src/base/Instance.cs

index 9f566b4e546c6d06fbf4fdd518796e40a05db932..81a78f6f7ac6e2cefe5ece7239f75e7b027ce197 100644 (file)
@@ -34,7 +34,7 @@
        </ItemGroup>
        
        <ItemGroup>
-               <PackageReference Include="SpirVTasks" Version="0.1.37-beta" /> 
+               <PackageReference Include="SpirVTasks" Version="0.1.38-beta" /> 
                <PackageReference Include="System.Numerics.Vectors" Version="4.5.0" />                  
        </ItemGroup>    
        
diff --git a/appveyor.yml b/appveyor.yml
new file mode 100644 (file)
index 0000000..3f45e42
--- /dev/null
@@ -0,0 +1,19 @@
+version: 1.0.{build}
+image: Visual Studio 2019
+
+environment:
+    VULKAN_SDK: C:/VulkanSDK/1.1.130.0
+    APPVEYOR_SAVE_CACHE_ON_ERROR: true
+
+cache:
+    - VulkanSDK.exe
+    - c:\VulkanSDK\
+
+install:
+    - if not exist VulkanSDK.exe curl -L --silent --show-error --output VulkanSDK.exe https://vulkan.lunarg.com/sdk/download/1.1.130.0/windows/VulkanSDK-1.1.130.0-Installer.exe?Human=true && VulkanSDK.exe /S
+
+before_build:
+  - nuget restore
+
+build:
+  verbosity: minimal
index f6d84427767019e0423c3d2cc622d52933ae4f9a..0f2b9a8e3c3a4713e589befd0781105c2139fcae 100644 (file)
@@ -10,8 +10,8 @@
                <Authors>Jean-Philippe Bruyère</Authors>
 
                <OutputPath>$(SolutionDir)build\$(Configuration)\</OutputPath>
-               <OutputType>Exe</OutputType>        
-               <AllowUnsafeBlocks>true</AllowUnsafeBlocks>
+               <OutputType>Exe</OutputType>
+               <!--<AllowUnsafeBlocks>true</AllowUnsafeBlocks>-->
                <IncludeDefaultNoneItems>false</IncludeDefaultNoneItems>
 
                <SpirVAdditionalIncludeDirectories>$(MSBuildThisFileDirectory)common\shaders</SpirVAdditionalIncludeDirectories>
@@ -33,7 +33,7 @@
        </ItemGroup>
                        
        <ItemGroup>
-               <PackageReference Include="SpirVTasks" Version="0.1.37-beta" />         
+               <PackageReference Include="SpirVTasks" Version="0.1.38-beta" />         
        </ItemGroup>    
 
        <ItemGroup>    
index 4d856a02a8af47a46b288ae0c3faa1b6e313cb3b..fd98d3cc6c4009812c77b633cfca06f2392afff2 100644 (file)
@@ -1,10 +1,14 @@
 
 Microsoft Visual Studio Solution File, Format Version 12.00
 # Visual Studio 15
-Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "addons", "addons", "{4AA67AB0-C331-4CB2-9C00-B74F5DE31658}"
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "SpirVTasks", "SpirVTasks\SpirVTasks.csproj", "{7B05B5A7-49E2-4D05-BEF8-734F70CDBF17}"
 EndProject
 Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "vke", "vke\vke.csproj", "{642726F4-0592-4846-8EAF-A5D1964C85A7}"
 EndProject
+Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "addons", "addons", "{4AA67AB0-C331-4CB2-9C00-B74F5DE31658}"
+EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "EnvironmentPipeline", "addons\EnvironmentPipeline\EnvironmentPipeline.csproj", "{F04C3F79-2E08-4D35-A804-43039DCB7F5E}"
+EndProject
 Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "DistanceFieldFont", "addons\DistanceFieldFont\DistanceFieldFont.csproj", "{FEF3AF30-5B88-4D3C-8BD7-8734200E0D1E}"
 EndProject
 Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "gltfLoader", "addons\gltfLoader\gltfLoader.csproj", "{F3BBF67D-7E63-48F3-8156-ADC014D268BB}"
@@ -13,26 +17,26 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "VkvgPipeline", "addons\Vkvg
 EndProject
 Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "samples", "samples", "{16439374-B8DB-4643-8116-EB3358B49A12}"
 EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Triangle", "samples\Triangle\Triangle.csproj", "{124152F8-FAE6-4D4B-87B9-6074DD365E9B}"
+EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Textured", "samples\Textured\Textured.csproj", "{1B2DF710-E500-49E5-8802-EBA71A05E827}"
+EndProject
 Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "compute", "samples\compute\compute.csproj", "{5000CDE2-99B9-47EA-B4D9-EA1631F0E14A}"
 EndProject
 Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "DistanceFieldFontTest", "samples\DistanceFieldFontTest\DistanceFieldFontTest.csproj", "{77437C6D-28B5-4798-96CA-68F987770D65}"
 EndProject
 Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Model", "samples\Model\Model.csproj", "{A7D3FB7F-769B-4F36-9E3E-3FB71F24D306}"
 EndProject
-Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Textured", "samples\Textured\Textured.csproj", "{1B2DF710-E500-49E5-8802-EBA71A05E827}"
-EndProject
 Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "TexturedCube", "samples\TexturedCube\TexturedCube.csproj", "{8185163E-A67C-4C0E-8548-67E2A9F16309}"
 EndProject
-Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "SpirVTasks", "SpirVTasks\SpirVTasks.csproj", "{7B05B5A7-49E2-4D05-BEF8-734F70CDBF17}"
-EndProject
-Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "EnvironmentPipeline", "addons\EnvironmentPipeline\EnvironmentPipeline.csproj", "{F04C3F79-2E08-4D35-A804-43039DCB7F5E}"
-EndProject
 Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "deferred", "samples\deferred\deferred.csproj", "{D9A41382-444E-44ED-B638-3D8F06F2FBC2}"
 EndProject
-Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Triangle", "samples\Triangle\Triangle.csproj", "{124152F8-FAE6-4D4B-87B9-6074DD365E9B}"
-EndProject
 Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "pbr", "samples\pbr\pbr.csproj", "{7EB2430B-6BC0-4AE9-B1FA-57C3DB2AE1C5}"
 EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "vkeEditor", "samples\vkeEditor\vkeEditor.csproj", "{81619805-9E6F-404A-BC0D-A2C25DDA2EDC}"
+EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "tests", "samples\tests\tests.csproj", "{F9117397-E105-44DD-A9BD-F6F8DC641095}"
+EndProject
 Global
        GlobalSection(SolutionConfigurationPlatforms) = preSolution
                Debug|Any CPU = Debug|Any CPU
@@ -146,6 +150,26 @@ Global
                {7EB2430B-6BC0-4AE9-B1FA-57C3DB2AE1C5}.DebugCrow|Any CPU.Build.0 = Debug|Any CPU
                {7EB2430B-6BC0-4AE9-B1FA-57C3DB2AE1C5}.Release|Any CPU.Build.0 = Release|Any CPU
                {7EB2430B-6BC0-4AE9-B1FA-57C3DB2AE1C5}.BuildPackages|Any CPU.ActiveCfg = Release|Any CPU
+               {81619805-9E6F-404A-BC0D-A2C25DDA2EDC}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+               {81619805-9E6F-404A-BC0D-A2C25DDA2EDC}.Debug|Any CPU.Build.0 = Debug|Any CPU
+               {81619805-9E6F-404A-BC0D-A2C25DDA2EDC}.Release|Any CPU.ActiveCfg = Release|Any CPU
+               {81619805-9E6F-404A-BC0D-A2C25DDA2EDC}.Release|Any CPU.Build.0 = Release|Any CPU
+               {81619805-9E6F-404A-BC0D-A2C25DDA2EDC}.DebugCrow|Any CPU.ActiveCfg = Debug|Any CPU
+               {81619805-9E6F-404A-BC0D-A2C25DDA2EDC}.DebugCrow|Any CPU.Build.0 = Debug|Any CPU
+               {81619805-9E6F-404A-BC0D-A2C25DDA2EDC}.ReleaseSpirVTasks|Any CPU.ActiveCfg = Debug|Any CPU
+               {81619805-9E6F-404A-BC0D-A2C25DDA2EDC}.ReleaseSpirVTasks|Any CPU.Build.0 = Debug|Any CPU
+               {81619805-9E6F-404A-BC0D-A2C25DDA2EDC}.BuildPackages|Any CPU.ActiveCfg = Release|Any CPU
+               {81619805-9E6F-404A-BC0D-A2C25DDA2EDC}.BuildPackages|Any CPU.Build.0 = Release|Any CPU
+               {F9117397-E105-44DD-A9BD-F6F8DC641095}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+               {F9117397-E105-44DD-A9BD-F6F8DC641095}.Debug|Any CPU.Build.0 = Debug|Any CPU
+               {F9117397-E105-44DD-A9BD-F6F8DC641095}.Release|Any CPU.ActiveCfg = Release|Any CPU
+               {F9117397-E105-44DD-A9BD-F6F8DC641095}.Release|Any CPU.Build.0 = Release|Any CPU
+               {F9117397-E105-44DD-A9BD-F6F8DC641095}.DebugCrow|Any CPU.ActiveCfg = Debug|Any CPU
+               {F9117397-E105-44DD-A9BD-F6F8DC641095}.DebugCrow|Any CPU.Build.0 = Debug|Any CPU
+               {F9117397-E105-44DD-A9BD-F6F8DC641095}.ReleaseSpirVTasks|Any CPU.ActiveCfg = Debug|Any CPU
+               {F9117397-E105-44DD-A9BD-F6F8DC641095}.ReleaseSpirVTasks|Any CPU.Build.0 = Debug|Any CPU
+               {F9117397-E105-44DD-A9BD-F6F8DC641095}.BuildPackages|Any CPU.ActiveCfg = Release|Any CPU
+               {F9117397-E105-44DD-A9BD-F6F8DC641095}.BuildPackages|Any CPU.Build.0 = Release|Any CPU
        EndGlobalSection
        GlobalSection(NestedProjects) = preSolution
                {FEF3AF30-5B88-4D3C-8BD7-8734200E0D1E} = {4AA67AB0-C331-4CB2-9C00-B74F5DE31658}
@@ -160,6 +184,8 @@ Global
                {D9A41382-444E-44ED-B638-3D8F06F2FBC2} = {16439374-B8DB-4643-8116-EB3358B49A12}
                {124152F8-FAE6-4D4B-87B9-6074DD365E9B} = {16439374-B8DB-4643-8116-EB3358B49A12}
                {7EB2430B-6BC0-4AE9-B1FA-57C3DB2AE1C5} = {16439374-B8DB-4643-8116-EB3358B49A12}
+               {81619805-9E6F-404A-BC0D-A2C25DDA2EDC} = {16439374-B8DB-4643-8116-EB3358B49A12}
+               {F9117397-E105-44DD-A9BD-F6F8DC641095} = {16439374-B8DB-4643-8116-EB3358B49A12}
        EndGlobalSection
        GlobalSection(MonoDevelopProperties) = preSolution
                Policies = $0
diff --git a/vke/netfx.props b/vke/netfx.props
deleted file mode 120000 (symlink)
index 728e74b..0000000
+++ /dev/null
@@ -1 +0,0 @@
-../netfx.props
\ No newline at end of file
index fab1325a0c274851360eb0360ed27ae888f2ba07..ecb6ac2facf560c7e0f1a00f6eda581111bbb912 100644 (file)
@@ -16,15 +16,19 @@ namespace vke {
        /// Provide default swapchain with its command pool and buffers per image and the main present queue
        /// </summary>
        public abstract class VkWindow : IDisposable {
-               static Dictionary<IntPtr,VkWindow> windows = new Dictionary<IntPtr, VkWindow>();
 
+               /** GLFW callback may return a custom pointer, this list makes the link between the GLFW window pointer and the
+                       manage VkWindow instance. */            
+               static Dictionary<IntPtr,VkWindow> windows = new Dictionary<IntPtr, VkWindow>();
+               /** GLFW window native pointer. */
                IntPtr hWin;
                /**Vulkan Surface */
                protected VkSurfaceKHR hSurf;
                /**vke Instance encapsulating a VkInstance. */
                protected Instance instance;    
                /**vke Physical device associated with this window*/
-               protected PhysicalDevice phy;   
+               protected PhysicalDevice phy;
+               /**vke logical device */                        
                protected Device dev;
                protected PresentQueue presentQueue;
                protected SwapChain swapChain;
@@ -33,14 +37,14 @@ namespace vke {
                protected VkSemaphore[] drawComplete;
                protected VkFence drawFence;
 
-               protected uint fps;
+               protected uint fps { get; private set; }
                protected bool updateViewRequested = true;
-               protected double lastMouseX, lastMouseY;
+               protected double lastMouseX { get; private set; }
+               protected double lastMouseY { get; private set; }
                protected bool[] MouseButton => buttons;
 
-               /// <summary>
-               /// default camera
-               /// </summary>
+
+               /**Default camera initialized with a Field of view of 40° and and aspect ratio of 1. */
                protected Camera camera = new Camera (Utils.DegreesToRadians (45f), 1f);
 
                bool[] buttons = new bool[10];
@@ -66,16 +70,24 @@ namespace vke {
 
                public uint Width { get; private set; }
                public uint Height { get; private set; }
+               public bool VSync { get; private set; }
                public string Title {
                        set {
                                Glfw3.SetWindowTitle (hWin, value);
                        }
                }
-
+               /// <summary>
+               /// Create a new vulkan enabled window with GLFW.
+               /// </summary>
+               /// <param name="name">Caption of the window</param>
+               /// <param name="_width">Width.</param>
+               /// <param name="_height">Height.</param>
+               /// <param name="vSync">Vertical synchronisation status for creating the swapchain.</param>
                public VkWindow (string name = "VkWindow", uint _width = 800, uint _height = 600, bool vSync = false) {
 
                        Width = _width;
                        Height = _height;
+                       VSync = vSync;
 
                        Glfw3.Init ();
 
@@ -95,22 +107,39 @@ namespace vke {
                        Glfw3.SetCharCallback (hWin, HandleCharDelegate);
 
                        windows.Add (hWin, this);
-
-                       initVulkan (vSync);
                }
-
+               /// <summary>
+               /// Set current mouse cursor in the GLFW window.
+               /// </summary>
+               /// <param name="cursor">New mouse cursor to set.</param>
                public void SetCursor (CursorShape cursor) {
                        if (currentCursor != IntPtr.Zero)
                                Glfw3.DestroyCursor (currentCursor);
                        currentCursor = Glfw3.CreateStandardCursor (cursor);
                        Glfw3.SetCursor (hWin, currentCursor);
                }
+               /// <summary>
+               /// Ask GLFW to close the native window.
+               /// </summary>
                public void Close ()
                {
                        Glfw3.SetWindowShouldClose (hWin, 1);
                }
-
-               void initVulkan (bool vSync) {
+               /// <summary>
+               /// Create the minimum vulkan objects to quickly start a new application. The folowing objects are created:
+               /// - Vulkan Instance with extensions present in the `EnabledInstanceExtensions` property.
+               /// - Vulkan Surface for the GLFW native window.
+               /// - Vulkan device for the selected physical one with configured enabledFeatures and extensions present in `EnabledDeviceExtensions` list. Selection of the default physical device
+               ///   may be replaced by the `selectPhysicalDevice` method override.
+               /// - Create a default Graphic Queue with presentable support. The default queue creation may be customized by overriding the `createQueues` method.
+               /// - Default vulkan Swapchain creation. Some swapchain's parameters are controled through static fields of the `SwapChain` class (ex: `SwapChain.PREFERED_FORMAT`).
+               /// - Create a default command pool for the `presentQueue` family index.
+               /// - Create an empty command buffer collection (`cmds`).
+               /// - Create one unsignaled vulkan semaphore (named `drawComplete` per swapchain image used to control presentation submission to the graphic queue.
+               /// - Create a signaled vulkan fence (`drawFence`). (TODO: improve this.
+               /// With all these objects, vulkan application programming startup is reduced to the minimal.
+               /// </summary>
+               protected virtual void initVulkan () {
                        List<string> instExts = new List<string> (Glfw3.GetRequiredInstanceExtensions ());
                        if (EnabledInstanceExtensions != null)
                                instExts.AddRange (EnabledInstanceExtensions);
@@ -119,14 +148,14 @@ namespace vke {
 
                        hSurf = instance.CreateSurface (hWin);
 
-                       phy = instance.GetAvailablePhysicalDevice ().FirstOrDefault (p => p.HasSwapChainSupport);
+                       selectPhysicalDevice ();
 
                        VkPhysicalDeviceFeatures enabledFeatures = default;
                        configureEnabledFeatures (phy.Features, ref enabledFeatures);
 
                        //First create the c# device class
                        dev = new Device (phy);
-                       dev.debugUtilsEnabled = instance.debugUtilsEnabled;
+                       dev.debugUtilsEnabled = instance.debugUtilsEnabled;//store a boolean to prevent testing against the extension string presence.
 
                        //create queue class
                        createQueues ();
@@ -135,7 +164,7 @@ namespace vke {
                        dev.Activate (enabledFeatures, EnabledDeviceExtensions);
 
                        swapChain = new SwapChain (presentQueue as PresentQueue, Width, Height, SwapChain.PREFERED_FORMAT,
-                               vSync ? VkPresentModeKHR.FifoKHR : VkPresentModeKHR.MailboxKHR);
+                               VSync ? VkPresentModeKHR.FifoKHR : VkPresentModeKHR.MailboxKHR);
                        swapChain.Create ();
 
                        Width = swapChain.Width;
@@ -156,12 +185,19 @@ namespace vke {
                }
                /// <summary>
                /// Override this method to modify enabled features before device creation. Feature availability is given by the first argument.
+               /// By default, no features is selected.
                /// </summary>
                /// <param name="available_features">Available features for the selected vulkan physical device associated with this window</param>
                /// <param name="enabled_features">Set boolean fileds of this structure to true to enable features.</param>
                protected virtual void configureEnabledFeatures (VkPhysicalDeviceFeatures available_features, ref VkPhysicalDeviceFeatures enabled_features) {
                }
                /// <summary>
+               /// Override this method to select another device than the first one with a swapchain support.
+               /// </summary>
+               protected virtual void selectPhysicalDevice () {
+                       phy = instance.GetAvailablePhysicalDevice ().FirstOrDefault (p => p.HasSwapChainSupport);
+               }
+               /// <summary>
                /// Override this method to create additional queue. Dedicated queue of the requested type will be selected first, created queues may excess
                /// available physical queues.
                /// </summary>
@@ -279,9 +315,20 @@ namespace vke {
                #endregion
 
                /// <summary>
-               /// main window loop, exits on GLFW3 exit event
+               /// main window loop, exits on GLFW3 exit event. Before entering the rendering loop, the following methods are called:
+               /// - initVulkan (device, queues and swapchain creations).
+               /// - OnResize (create there your frame buffers couple to the swapchain and trigger the recording of your command buffers for the presentation.
+               /// - UpdateView (generaly used when the camera setup has changed to update MVP matrices)
+               /// The rendering loop consist of the following steps:
+               /// - render (the default one will submit the default command buffers to the presentQueue and trigger a queue present for each swapchain images.
+               /// - if the `updateViewRequested` field is set to 'true', call the `UpdateView` method.
+               /// - frame counting and chrono.
+               /// - if elapsed time reached `UpdateFrequency` value, the `Update` method is called and the elapsed time chrono is reseet.
+               /// - GLFW events are polled at the end of the loop. 
                /// </summary>
                public virtual void Run () {
+                       initVulkan ();
+
                        OnResize ();
                        UpdateView ();
 
@@ -314,20 +361,21 @@ namespace vke {
                }
                /// <summary>
                /// Suitable for updating the matrices, called at least once before the rendering loop just
-               /// after 'OnResize'. Then, triggered each time 'updateViewRequested' is true in the render loop, don't forget to
+               /// after 'OnResize'. Then, triggered in the render loop each time the 'updateViewRequested' field is set to 'true', don't forget to
                /// reset 'updateViewRequested' to 'false' or call the 'base.UpdateView()' which will reset this boolean.
                /// </summary>
                public virtual void UpdateView () {
                        updateViewRequested = false;
                }
                /// <summary>
-               /// custom update method called at UpdateFrequency, base method is empty.
+               /// custom update method called controled by the `UpdateFrequency` field, base method is empty.
                /// </summary>
                public virtual void Update () { }
 
                /// <summary>
                /// Called when swapchain has been resized, override this method to resize your framebuffers coupled to the swapchain.
-               /// The base method will update Window 'Width' and 'Height' properties with new swapchain's dimensions.
+               /// The base method will update Window 'Width' and 'Height' properties with new swapchain's dimensions. This method is guarantied to
+               /// be called once just after `initVulkan` and before the first render.
                /// </summary>
                protected virtual void OnResize () {
                        Width = swapChain.Width;
index 6e60f8de76ffc89060c5b08a68f06e4b489f67a5..5fc2a99b4365fd0515acabc47fa8da12c836b920 100644 (file)
@@ -8,7 +8,7 @@ using static Vulkan.Vk;
 
 namespace vke {
        /// <summary>
-       /// Tristate status of activables, reflecting vulkan openrations
+       /// Tristate status of activables, reflecting vulkan operations
        /// </summary>
        public enum ActivableState {
                /// <summary>
@@ -38,10 +38,10 @@ namespace vke {
                [XmlIgnore] protected uint references;
                //keep track of the current state of activation.
                protected ActivableState state;
-               //With the debug marker extension, setting name to vulkan's object ease the debugging.
+               //With the debug utils extension, setting name to vulkan's object ease the debugging.
                protected string name;
                /// <summary>
-               /// This property has to be implemented in every vulkan object. It should return the correct debug marker info.
+               /// This property has to be implemented in every vulkan object. It must return the correct debug marker info.
                /// </summary>
                /// <value>The debug marker info.</value>
                protected abstract VkDebugUtilsObjectNameInfoEXT DebugUtilsInfo { get; }
index beb415a1dc471079db4b91424f51a37fd24e85be..b4fdc70bd9d1e0ae651af9fe1453971d179e57c3 100644 (file)
@@ -91,7 +91,7 @@ namespace vke {
                                Vk.LoadInstanceFunctionPointers (inst);
                        }
                }
-
+               public string[] SupportedExtensions () => SupportedExtensions (IntPtr.Zero);
                public string[] SupportedExtensions (IntPtr layer) {
                        Utils.CheckResult (vkEnumerateInstanceExtensionProperties (layer, out uint count, IntPtr.Zero));