]> O.S.I.I.S - jp/vke.net.git/commitdiff
rename utils.cs to helpers.cs
authorJean-Philippe Bruyère <jp_bruyere@hotmail.com>
Thu, 9 Dec 2021 15:39:38 +0000 (16:39 +0100)
committerJean-Philippe Bruyère <jp_bruyere@hotmail.com>
Thu, 9 Dec 2021 15:39:38 +0000 (16:39 +0100)
vke/src/Helpers.cs [new file with mode: 0644]
vke/src/Utils.cs [deleted file]

diff --git a/vke/src/Helpers.cs b/vke/src/Helpers.cs
new file mode 100644 (file)
index 0000000..86d026b
--- /dev/null
@@ -0,0 +1,482 @@
+// Copyright (c) 2019-2022  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.IO;
+using System.Linq;
+using System.Numerics;
+using System.Reflection;
+using System.Runtime.CompilerServices;
+using System.Runtime.InteropServices;
+using System.Xml.Serialization;
+using Vulkan;
+
+namespace vke {
+       public static partial class Helpers {
+               /// <summary>Throw an erro if VkResult != Success.</summary>
+               static void xmlMakeTypeFieldsAsAttributes (Type t, ref XmlAttributeOverrides overrides)
+               {
+                       foreach (FieldInfo fi in t.GetFields (BindingFlags.Public | BindingFlags.Instance))
+                               overrides.Add (t, fi.Name, new XmlAttributes { XmlAttribute = new XmlAttributeAttribute () });
+               }
+               public static XmlAttributeOverrides GetXmlOverrides ()
+               {
+                       XmlAttributeOverrides xmlAttributeOverrides = new XmlAttributeOverrides ();
+                       //Assembly avk = Assembly.GetAssembly (typeof (VkInstance));
+                       xmlMakeTypeFieldsAsAttributes (typeof (VkDescriptorPoolSize), ref xmlAttributeOverrides);
+                       return xmlAttributeOverrides;
+               }
+               static bool tryFindResource (Assembly a, string resId, out Stream stream) {
+                       stream = null;
+                       if (a == null)
+                               return false;
+                       stream = a.GetManifestResourceStream (resId);
+                       return stream != null;
+               }
+               /// <summary>
+               /// Return a file or embedded resource stream.
+               /// </summary>
+               /// <remarks>
+               /// Embedded resource path start with `#`. The entry assembly is always searched first to be able
+               /// to override resource defined in satellite assemblies.
+               /// To enforce assembly name selection, use `:` to split assembly and resource (ex; "Assembly:LogicalName"),
+               /// else assembly names will be determined with the first, or the two firsts names in the path string.
+               /// (ex: AssemblyName.filename.ext then Assembly.Name.filename.ext)
+               /// </remarks>
+               /// <returns>The stream from path.</returns>
+               /// <param name="path">The file or stream path. Embedded resource path starts with '#' or contains ':'.</param>
+               public static Stream GetStreamFromPath (string path) {
+                       if (path.StartsWith("#", StringComparison.Ordinal))
+                       {
+                               Stream stream = null;
+                               string[] assemblyNames = null;
+                               Assembly assembly = null;
+
+                               string resId = path.Substring(1);
+
+                               if (tryFindResource(Assembly.GetEntryAssembly(), resId, out stream))
+                                       return stream;
+
+                               if (path.Contains(":", StringComparison.Ordinal)) {
+                                       assemblyNames = resId.Split (':');
+                                       assembly = AppDomain.CurrentDomain.GetAssemblies ().FirstOrDefault (aa => aa.GetName ().Name == assemblyNames[0]);
+                                       if (assembly == null)
+                                               throw new Exception("Assembly not found: " + path);
+                                       if (tryFindResource(assembly, assemblyNames[1], out stream))
+                                               return stream;
+                                       throw new Exception("Embedded resource not found in assembly: " + path);
+                               }
+
+                               assemblyNames = resId.Split('.');
+                               assembly = AppDomain.CurrentDomain.GetAssemblies().FirstOrDefault(aa => aa.GetName().Name == assemblyNames[0]);
+                               if (assembly == null && assemblyNames.Length > 3)
+                                       assembly = AppDomain.CurrentDomain.GetAssemblies()
+                                               .FirstOrDefault(aa => aa.GetName().Name == $"{assemblyNames[0]}.{assemblyNames[1]}");
+                               if (assembly != null && tryFindResource(assembly, resId, out stream))
+                                       return stream;
+                               throw new Exception("Resource not found: " + path);
+                       }
+                       if (!File.Exists (path))
+                               throw new FileNotFoundException ("File not found: ", path);
+                       return new FileStream (path, FileMode.Open, FileAccess.Read);
+               }
+               /// <summary>Convert angle from degree to radian.</summary>
+               public static float DegreesToRadians (float degrees) {
+                       return degrees * (float)Math.PI / 180f;
+               }
+
+               /// <summary>
+               /// Populate a Vector3 with values from a float array
+               /// </summary>
+               public static void FromFloatArray (ref Vector3 v, float[] floats) {
+                       v = Unsafe.As<float[], Vector3[]>(ref floats)[0];
+               }
+               /// <summary>
+               /// Populate a Vector4 with values from a float array
+               /// </summary>
+               public static void FromFloatArray (ref Vector4 v, float[] floats) {
+                       MemoryMarshal.Cast<float, Vector4>(floats.AsSpan());
+               }
+               /// <summary>
+               /// Populate a Quaternion with values from a float array
+               /// </summary>
+               public static void FromFloatArray (ref Quaternion q, float[] floats) {
+                       q = Unsafe.As<float[], Quaternion[]>(ref floats)[0];
+               }
+               /// <summary>
+               /// Populate a Vector2 with values from a byte array starting at offset
+               /// </summary>
+               public static void FromByteArray (ref Vector2 v, byte[] byteArray, int offset) {
+                       v = Unsafe.As<byte[], Vector2[]>(ref Unsafe.AsRef(byteArray.SubArray(offset, 8)))[0];
+               }
+               /// <summary>
+               /// Populate a Vector3 with values from a byte array starting at offset
+               /// </summary>
+               public static void FromByteArray (ref Vector3 v, byte[] byteArray, int offset) {
+                       v = Unsafe.As<byte[], Vector3[]>(ref Unsafe.AsRef(byteArray.SubArray(offset, 12)))[0];
+               }
+               /// <summary>
+               /// Populate a Vector4 with values from a byte array starting at offset
+               /// </summary>
+               public static void FromByteArray (ref Vector4 v, byte[] byteArray, int offset) {
+                       v = Unsafe.As<byte[], Vector4[]>(ref Unsafe.AsRef(byteArray.SubArray(offset, 16)))[0];
+               }
+               /// <summary>
+               /// Populate a Quaternion with values from a byte array starting at offset
+               /// </summary>
+               public static void FromByteArray (ref Quaternion v, byte[] byteArray, int offset) {
+                       v = Unsafe.As<byte[], Quaternion[]>(ref Unsafe.AsRef(byteArray.SubArray(offset, 16)))[0];
+               }
+
+               #region Extensions methods
+               public static void ImportFloatArray (this ref Vector3 v, float[] floats) {
+                       v = Unsafe.As<float[], Vector3[]>(ref floats)[0];
+               }
+               public static Vector3 Transform (this Vector3 v, ref Matrix4x4 mat, bool translate = false) {
+                       Vector4 v4 = Vector4.Transform (new Vector4 (v, translate ? 1f : 0f), mat);
+                       return new Vector3 (v4.X, v4.Y, v4.Z);
+               }
+               public static Vector3 ToVector3 (this Vector4 v) {
+                       return Unsafe.As<Vector4, Vector3>(ref v);
+               }
+               public static T[] SubArray<T>(this T[] array, int offset, int length)
+               {
+                       T[] result = new T[length];
+                       Array.Copy(array, offset, result, 0, length);
+                       return result;
+               }
+               #endregion
+
+               // Fixed sub resource on first mip level and layer
+               public static void setImageLayout (
+                       VkCommandBuffer cmdbuffer,
+                       VkImage image,
+                       VkImageAspectFlags aspectMask,
+                       VkImageLayout oldImageLayout,
+                       VkImageLayout newImageLayout,
+                       VkPipelineStageFlags srcStageMask = VkPipelineStageFlags.AllCommands,
+                       VkPipelineStageFlags dstStageMask = VkPipelineStageFlags.AllCommands) {
+                       VkImageSubresourceRange subresourceRange = new VkImageSubresourceRange {
+                               aspectMask = aspectMask,
+                               baseMipLevel = 0,
+                               levelCount = 1,
+                               layerCount = 1,
+                       };
+                       setImageLayout (cmdbuffer, image, aspectMask, oldImageLayout, newImageLayout, subresourceRange);
+               }
+
+               // Create an image memory barrier for changing the layout of
+               // an image and put it into an active command buffer
+               // See chapter 11.4 "Image Layout" for details
+
+               public static void setImageLayout (
+                       VkCommandBuffer cmdbuffer,
+                       VkImage image,
+                       VkImageAspectFlags aspectMask,
+                       VkImageLayout oldImageLayout,
+                       VkImageLayout newImageLayout,
+                       VkImageSubresourceRange subresourceRange,
+                       VkPipelineStageFlags srcStageMask = VkPipelineStageFlags.AllCommands,
+                       VkPipelineStageFlags dstStageMask = VkPipelineStageFlags.AllCommands) {
+                       // Create an image barrier object
+                       VkImageMemoryBarrier imageMemoryBarrier = default;
+                       imageMemoryBarrier.srcQueueFamilyIndex = Vk.QueueFamilyIgnored;
+                       imageMemoryBarrier.dstQueueFamilyIndex = Vk.QueueFamilyIgnored;
+                       imageMemoryBarrier.oldLayout = oldImageLayout;
+                       imageMemoryBarrier.newLayout = newImageLayout;
+                       imageMemoryBarrier.image = image;
+                       imageMemoryBarrier.subresourceRange = subresourceRange;
+
+                       // Source layouts (old)
+                       // Source access mask controls actions that have to be finished on the old layout
+                       // before it will be transitioned to the new layout
+                       switch (oldImageLayout) {
+                               case VkImageLayout.Undefined:
+                                       // Image layout is undefined (or does not matter)
+                                       // Only valid as initial layout
+                                       // No flags required, listed only for completeness
+                                       imageMemoryBarrier.srcAccessMask = 0;
+                                       break;
+
+                               case VkImageLayout.Preinitialized:
+                                       // Image is preinitialized
+                                       // Only valid as initial layout for linear images, preserves memory contents
+                                       // Make sure host writes have been finished
+                                       imageMemoryBarrier.srcAccessMask = VkAccessFlags.HostWrite;
+                                       break;
+
+                               case VkImageLayout.ColorAttachmentOptimal:
+                                       // Image is a color attachment
+                                       // Make sure any writes to the color buffer have been finished
+                                       imageMemoryBarrier.srcAccessMask = VkAccessFlags.ColorAttachmentWrite;
+                                       break;
+
+                               case VkImageLayout.DepthStencilAttachmentOptimal:
+                                       // Image is a depth/stencil attachment
+                                       // Make sure any writes to the depth/stencil buffer have been finished
+                                       imageMemoryBarrier.srcAccessMask = VkAccessFlags.DepthStencilAttachmentWrite;
+                                       break;
+
+                               case VkImageLayout.TransferSrcOptimal:
+                                       // Image is a transfer source
+                                       // Make sure any reads from the image have been finished
+                                       imageMemoryBarrier.srcAccessMask = VkAccessFlags.TransferRead;
+                                       break;
+
+                               case VkImageLayout.TransferDstOptimal:
+                                       // Image is a transfer destination
+                                       // Make sure any writes to the image have been finished
+                                       imageMemoryBarrier.srcAccessMask = VkAccessFlags.TransferWrite;
+                                       break;
+
+                               case VkImageLayout.ShaderReadOnlyOptimal:
+                                       // Image is read by a shader
+                                       // Make sure any shader reads from the image have been finished
+                                       imageMemoryBarrier.srcAccessMask = VkAccessFlags.ShaderRead;
+                                       break;
+                       }
+
+                       // Target layouts (new)
+                       // Destination access mask controls the dependency for the new image layout
+                       switch (newImageLayout) {
+                               case VkImageLayout.TransferDstOptimal:
+                                       // Image will be used as a transfer destination
+                                       // Make sure any writes to the image have been finished
+                                       imageMemoryBarrier.dstAccessMask = VkAccessFlags.TransferWrite;
+                                       break;
+
+                               case VkImageLayout.TransferSrcOptimal:
+                                       // Image will be used as a transfer source
+                                       // Make sure any reads from and writes to the image have been finished
+                                       imageMemoryBarrier.srcAccessMask = imageMemoryBarrier.srcAccessMask | VkAccessFlags.TransferRead;
+                                       imageMemoryBarrier.dstAccessMask = VkAccessFlags.TransferRead;
+                                       break;
+
+                               case VkImageLayout.ColorAttachmentOptimal:
+                                       // Image will be used as a color attachment
+                                       // Make sure any writes to the color buffer have been finished
+                                       imageMemoryBarrier.srcAccessMask = VkAccessFlags.TransferRead;
+                                       imageMemoryBarrier.dstAccessMask = VkAccessFlags.ColorAttachmentWrite;
+                                       break;
+
+                               case VkImageLayout.DepthStencilAttachmentOptimal:
+                                       // Image layout will be used as a depth/stencil attachment
+                                       // Make sure any writes to depth/stencil buffer have been finished
+                                       imageMemoryBarrier.dstAccessMask = imageMemoryBarrier.dstAccessMask | VkAccessFlags.DepthStencilAttachmentWrite;
+                                       break;
+
+                               case VkImageLayout.ShaderReadOnlyOptimal:
+                                       // Image will be read in a shader (sampler, input attachment)
+                                       // Make sure any writes to the image have been finished
+                                       if (imageMemoryBarrier.srcAccessMask == 0) {
+                                               imageMemoryBarrier.srcAccessMask = VkAccessFlags.HostWrite | VkAccessFlags.TransferWrite;
+                                       }
+                                       imageMemoryBarrier.dstAccessMask = VkAccessFlags.ShaderRead;
+                                       break;
+                       }
+
+                       // Put barrier inside setup command buffer
+                       Vk.vkCmdPipelineBarrier (
+                               cmdbuffer,
+                               srcStageMask,
+                               dstStageMask,
+                               0,
+                               0, IntPtr.Zero,
+                               0, IntPtr.Zero,
+                               1, ref imageMemoryBarrier);
+               }
+               /// <summary>
+               /// Find usage flags and aspect flag from image layout
+               /// </summary>
+               public static void QueryLayoutRequirements (VkImageLayout layout, ref VkImageUsageFlags usage, ref VkImageAspectFlags aspectFlags) {
+                       switch (layout) {
+                               case VkImageLayout.ColorAttachmentOptimal:
+                               case VkImageLayout.PresentSrcKHR:
+                               case VkImageLayout.SharedPresentKHR:
+                                       aspectFlags |= VkImageAspectFlags.Color;
+                                       if (usage.HasFlag (VkImageUsageFlags.Sampled))
+                                               usage |= VkImageUsageFlags.InputAttachment;
+                                       usage |= VkImageUsageFlags.ColorAttachment;
+                                       break;
+                               case VkImageLayout.DepthStencilAttachmentOptimal:
+                                       aspectFlags |= VkImageAspectFlags.Depth | VkImageAspectFlags.Stencil;
+                                       usage |= VkImageUsageFlags.DepthStencilAttachment;
+                                       break;
+                               case VkImageLayout.DepthStencilReadOnlyOptimal:
+                                       aspectFlags |= VkImageAspectFlags.Depth | VkImageAspectFlags.Stencil;
+                                       if (usage.HasFlag (VkImageUsageFlags.ColorAttachment))
+                                               usage |= VkImageUsageFlags.InputAttachment;
+                                       else
+                                               usage |= VkImageUsageFlags.Sampled;
+                                       break;
+                               case VkImageLayout.ShaderReadOnlyOptimal:
+                                       aspectFlags |= VkImageAspectFlags.Color;
+                                       usage |= VkImageUsageFlags.Sampled;
+                                       break;
+                               case VkImageLayout.TransferSrcOptimal:
+                                       usage |= VkImageUsageFlags.TransferSrc;
+                                       break;
+                               case VkImageLayout.TransferDstOptimal:
+                                       usage |= VkImageUsageFlags.TransferDst;
+                                       break;
+                               case VkImageLayout.DepthReadOnlyStencilAttachmentOptimalKHR:
+                               case VkImageLayout.DepthAttachmentStencilReadOnlyOptimalKHR:
+                                       aspectFlags |= VkImageAspectFlags.Depth | VkImageAspectFlags.Stencil;
+                                       usage |= VkImageUsageFlags.Sampled | VkImageUsageFlags.DepthStencilAttachment;
+                                       break;
+                       }
+               }
+               /// <summary>
+               /// Try to get the block width and height of a compressed format
+               /// </summary>
+               /// <returns><c>true</c>return true if format given as first argument is a compressed format.</returns>
+               /// <param name="format">Vulkan format to test.</param>
+               /// <param name="width">Compressed block width.</param>
+               /// <param name="height">Compressed block height.</param>
+               public static bool TryGetCompressedFormatBlockSize (this VkFormat format, out uint width, out uint height)
+               {
+                       width = height = 1;
+                       if (format < VkFormat.Bc1RgbUnormBlock || format > (VkFormat)1000066013) //VK_FORMAT_ASTC_12x12_SFLOAT_BLOCK_EXT)
+                               return false;
+                       if (format < VkFormat.Astc5x4UnormBlock)
+                               width = height = 4;
+                       else {
+                               string str = format.ToString ();
+                               if (str.StartsWith ("Astc", StringComparison.OrdinalIgnoreCase)) {
+                                       width = uint.Parse (str.Substring (4, 1));
+                                       height = uint.Parse (str.Substring (6, 1));
+                               }
+                       }
+
+                       return true;
+               }
+               //TODO:quick done list, refine needed
+               public static VkPipelineStageFlags GetDefaultStage (this VkImageLayout layout) {
+                       switch (layout) {
+                       case VkImageLayout.Preinitialized:
+                       case VkImageLayout.Undefined:
+                               return VkPipelineStageFlags.AllCommands;
+
+                       case VkImageLayout.General:
+                               return VkPipelineStageFlags.ComputeShader;
+
+                       case VkImageLayout.ColorAttachmentOptimal:
+                       case VkImageLayout.DepthStencilAttachmentOptimal:
+                               return VkPipelineStageFlags.ColorAttachmentOutput;
+
+                       case VkImageLayout.DepthStencilReadOnlyOptimal:
+                       case VkImageLayout.DepthReadOnlyStencilAttachmentOptimalKHR:
+                       case VkImageLayout.DepthAttachmentStencilReadOnlyOptimalKHR:
+                               return VkPipelineStageFlags.EarlyFragmentTests;
+
+                       case VkImageLayout.ShaderReadOnlyOptimal:
+                               return VkPipelineStageFlags.FragmentShader;
+
+                       case VkImageLayout.TransferSrcOptimal:
+                       case VkImageLayout.TransferDstOptimal:
+                               return VkPipelineStageFlags.Transfer;
+
+                       case VkImageLayout.PresentSrcKHR:
+                       case VkImageLayout.SharedPresentKHR:
+                               return VkPipelineStageFlags.ColorAttachmentOutput;
+
+                       //case VkImageLayout.ShadingRateOptimalNV:
+                       //case VkImageLayout.FragmentDensityMapOptimalEXT:
+                       default:
+                               return VkPipelineStageFlags.AllCommands;
+                       }
+               }
+               public static Matrix4x4 CreatePerspectiveFieldOfView (float fov, float aspectRatio, float zNear, float zFar) {
+                       float f = (float)(1.0 / System.Math.Tan (0.5 * fov));
+                       return new Matrix4x4 (
+                               f / aspectRatio, 0, 0, 0,
+                               0, -f, 0, 0,
+                               0, 0, zFar / (zNear - zFar), -1,
+                               0, 0, zNear * zFar / (zNear - zFar), 0
+                       );
+               }
+
+               public static VkShaderStageFlags ShaderKindToStageFlag (shaderc.ShaderKind shaderKind) {
+                       switch (shaderKind) {
+                       case shaderc.ShaderKind.VertexShader:
+                       case shaderc.ShaderKind.GlslDefaultVertexShader:
+                               return VkShaderStageFlags.Vertex;
+                       case shaderc.ShaderKind.FragmentShader:
+                       case shaderc.ShaderKind.GlslDefaultFragmentShader:
+                               return VkShaderStageFlags.Fragment;
+                       case shaderc.ShaderKind.ComputeShader:
+                       case shaderc.ShaderKind.GlslDefaultComputeShader:
+                               return VkShaderStageFlags.Compute;
+                       case shaderc.ShaderKind.GeometryShader:
+                       case shaderc.ShaderKind.GlslDefaultGeometryShader:
+                               return VkShaderStageFlags.Geometry;
+                       case shaderc.ShaderKind.TessControlShader:
+                       case shaderc.ShaderKind.GlslDefaultTessControlShader:
+                               return VkShaderStageFlags.TessellationControl;
+                       case shaderc.ShaderKind.TessEvaluationShader:
+                       case shaderc.ShaderKind.GlslDefaultTessEvaluationShader:
+                               return VkShaderStageFlags.TessellationEvaluation;
+                       case shaderc.ShaderKind.RaygenShader:
+                       case shaderc.ShaderKind.GlslDefaultRaygenShader:
+                               return VkShaderStageFlags.RaygenKHR;
+                       case shaderc.ShaderKind.AnyhitShader:
+                       case shaderc.ShaderKind.GlslDefaultAnyhitShader:
+                               return VkShaderStageFlags.AnyHitKHR;
+                       case shaderc.ShaderKind.ClosesthitShader:
+                       case shaderc.ShaderKind.GlslDefaultClosesthitShader:
+                               return VkShaderStageFlags.ClosestHitKHR;
+                       case shaderc.ShaderKind.MissShader:
+                       case shaderc.ShaderKind.GlslDefaultMissShader:
+                               return VkShaderStageFlags.MissKHR;
+                       case shaderc.ShaderKind.IntersectionShader:
+                       case shaderc.ShaderKind.GlslDefaultIntersectionShader:
+                               return VkShaderStageFlags.IntersectionKHR;
+                       case shaderc.ShaderKind.CallableShader:
+                       case shaderc.ShaderKind.GlslDefaultCallableShader:
+                               return VkShaderStageFlags.CallableKHR;
+                       case shaderc.ShaderKind.TaskShader:
+                       case shaderc.ShaderKind.GlslDefaultTaskShader:
+                               return VkShaderStageFlags.TaskNV;
+                       case shaderc.ShaderKind.MeshShader:
+                       case shaderc.ShaderKind.GlslDefaultMeshShader:
+                               return VkShaderStageFlags.MeshNV;
+                       default:
+                               throw new NotSupportedException ($"shaderc shaderKind {shaderKind} conversion to VK StageFlag  not handled");
+                       }
+               }
+               public static shaderc.ShaderKind ShaderStageToShaderKind (VkShaderStageFlags stageFlag) {
+                       switch (stageFlag) {
+                       case VkShaderStageFlags.Vertex:
+                               return shaderc.ShaderKind.VertexShader;
+                       case VkShaderStageFlags.TessellationControl:
+                               return shaderc.ShaderKind.TessControlShader;
+                       case VkShaderStageFlags.TessellationEvaluation:
+                               return shaderc.ShaderKind.TessEvaluationShader;
+                       case VkShaderStageFlags.Geometry:
+                               return shaderc.ShaderKind.GeometryShader;
+                       case VkShaderStageFlags.Fragment:
+                               return shaderc.ShaderKind.FragmentShader;
+                       case VkShaderStageFlags.Compute:
+                               return shaderc.ShaderKind.ComputeShader;
+                       case VkShaderStageFlags.RaygenKHR:
+                               return shaderc.ShaderKind.RaygenShader;
+                       case VkShaderStageFlags.AnyHitKHR:
+                               return shaderc.ShaderKind.AnyhitShader;
+                       case VkShaderStageFlags.ClosestHitKHR:
+                               return shaderc.ShaderKind.ClosesthitShader;
+                       case VkShaderStageFlags.MissKHR:
+                               return shaderc.ShaderKind.MissShader;
+                       case VkShaderStageFlags.IntersectionKHR:
+                               return shaderc.ShaderKind.IntersectionShader;
+                       case VkShaderStageFlags.CallableKHR:
+                               return shaderc.ShaderKind.CallableShader;
+                       case VkShaderStageFlags.TaskNV:
+                               return shaderc.ShaderKind.TaskShader;
+                       case VkShaderStageFlags.MeshNV:
+                               return shaderc.ShaderKind.MeshShader;
+                       default:
+                               throw new NotSupportedException ($"Error Shader Stage flag conversion to ShaderKind: {stageFlag}");
+                       }
+               }
+       }
+}
diff --git a/vke/src/Utils.cs b/vke/src/Utils.cs
deleted file mode 100644 (file)
index 86d026b..0000000
+++ /dev/null
@@ -1,482 +0,0 @@
-// Copyright (c) 2019-2022  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.IO;
-using System.Linq;
-using System.Numerics;
-using System.Reflection;
-using System.Runtime.CompilerServices;
-using System.Runtime.InteropServices;
-using System.Xml.Serialization;
-using Vulkan;
-
-namespace vke {
-       public static partial class Helpers {
-               /// <summary>Throw an erro if VkResult != Success.</summary>
-               static void xmlMakeTypeFieldsAsAttributes (Type t, ref XmlAttributeOverrides overrides)
-               {
-                       foreach (FieldInfo fi in t.GetFields (BindingFlags.Public | BindingFlags.Instance))
-                               overrides.Add (t, fi.Name, new XmlAttributes { XmlAttribute = new XmlAttributeAttribute () });
-               }
-               public static XmlAttributeOverrides GetXmlOverrides ()
-               {
-                       XmlAttributeOverrides xmlAttributeOverrides = new XmlAttributeOverrides ();
-                       //Assembly avk = Assembly.GetAssembly (typeof (VkInstance));
-                       xmlMakeTypeFieldsAsAttributes (typeof (VkDescriptorPoolSize), ref xmlAttributeOverrides);
-                       return xmlAttributeOverrides;
-               }
-               static bool tryFindResource (Assembly a, string resId, out Stream stream) {
-                       stream = null;
-                       if (a == null)
-                               return false;
-                       stream = a.GetManifestResourceStream (resId);
-                       return stream != null;
-               }
-               /// <summary>
-               /// Return a file or embedded resource stream.
-               /// </summary>
-               /// <remarks>
-               /// Embedded resource path start with `#`. The entry assembly is always searched first to be able
-               /// to override resource defined in satellite assemblies.
-               /// To enforce assembly name selection, use `:` to split assembly and resource (ex; "Assembly:LogicalName"),
-               /// else assembly names will be determined with the first, or the two firsts names in the path string.
-               /// (ex: AssemblyName.filename.ext then Assembly.Name.filename.ext)
-               /// </remarks>
-               /// <returns>The stream from path.</returns>
-               /// <param name="path">The file or stream path. Embedded resource path starts with '#' or contains ':'.</param>
-               public static Stream GetStreamFromPath (string path) {
-                       if (path.StartsWith("#", StringComparison.Ordinal))
-                       {
-                               Stream stream = null;
-                               string[] assemblyNames = null;
-                               Assembly assembly = null;
-
-                               string resId = path.Substring(1);
-
-                               if (tryFindResource(Assembly.GetEntryAssembly(), resId, out stream))
-                                       return stream;
-
-                               if (path.Contains(":", StringComparison.Ordinal)) {
-                                       assemblyNames = resId.Split (':');
-                                       assembly = AppDomain.CurrentDomain.GetAssemblies ().FirstOrDefault (aa => aa.GetName ().Name == assemblyNames[0]);
-                                       if (assembly == null)
-                                               throw new Exception("Assembly not found: " + path);
-                                       if (tryFindResource(assembly, assemblyNames[1], out stream))
-                                               return stream;
-                                       throw new Exception("Embedded resource not found in assembly: " + path);
-                               }
-
-                               assemblyNames = resId.Split('.');
-                               assembly = AppDomain.CurrentDomain.GetAssemblies().FirstOrDefault(aa => aa.GetName().Name == assemblyNames[0]);
-                               if (assembly == null && assemblyNames.Length > 3)
-                                       assembly = AppDomain.CurrentDomain.GetAssemblies()
-                                               .FirstOrDefault(aa => aa.GetName().Name == $"{assemblyNames[0]}.{assemblyNames[1]}");
-                               if (assembly != null && tryFindResource(assembly, resId, out stream))
-                                       return stream;
-                               throw new Exception("Resource not found: " + path);
-                       }
-                       if (!File.Exists (path))
-                               throw new FileNotFoundException ("File not found: ", path);
-                       return new FileStream (path, FileMode.Open, FileAccess.Read);
-               }
-               /// <summary>Convert angle from degree to radian.</summary>
-               public static float DegreesToRadians (float degrees) {
-                       return degrees * (float)Math.PI / 180f;
-               }
-
-               /// <summary>
-               /// Populate a Vector3 with values from a float array
-               /// </summary>
-               public static void FromFloatArray (ref Vector3 v, float[] floats) {
-                       v = Unsafe.As<float[], Vector3[]>(ref floats)[0];
-               }
-               /// <summary>
-               /// Populate a Vector4 with values from a float array
-               /// </summary>
-               public static void FromFloatArray (ref Vector4 v, float[] floats) {
-                       MemoryMarshal.Cast<float, Vector4>(floats.AsSpan());
-               }
-               /// <summary>
-               /// Populate a Quaternion with values from a float array
-               /// </summary>
-               public static void FromFloatArray (ref Quaternion q, float[] floats) {
-                       q = Unsafe.As<float[], Quaternion[]>(ref floats)[0];
-               }
-               /// <summary>
-               /// Populate a Vector2 with values from a byte array starting at offset
-               /// </summary>
-               public static void FromByteArray (ref Vector2 v, byte[] byteArray, int offset) {
-                       v = Unsafe.As<byte[], Vector2[]>(ref Unsafe.AsRef(byteArray.SubArray(offset, 8)))[0];
-               }
-               /// <summary>
-               /// Populate a Vector3 with values from a byte array starting at offset
-               /// </summary>
-               public static void FromByteArray (ref Vector3 v, byte[] byteArray, int offset) {
-                       v = Unsafe.As<byte[], Vector3[]>(ref Unsafe.AsRef(byteArray.SubArray(offset, 12)))[0];
-               }
-               /// <summary>
-               /// Populate a Vector4 with values from a byte array starting at offset
-               /// </summary>
-               public static void FromByteArray (ref Vector4 v, byte[] byteArray, int offset) {
-                       v = Unsafe.As<byte[], Vector4[]>(ref Unsafe.AsRef(byteArray.SubArray(offset, 16)))[0];
-               }
-               /// <summary>
-               /// Populate a Quaternion with values from a byte array starting at offset
-               /// </summary>
-               public static void FromByteArray (ref Quaternion v, byte[] byteArray, int offset) {
-                       v = Unsafe.As<byte[], Quaternion[]>(ref Unsafe.AsRef(byteArray.SubArray(offset, 16)))[0];
-               }
-
-               #region Extensions methods
-               public static void ImportFloatArray (this ref Vector3 v, float[] floats) {
-                       v = Unsafe.As<float[], Vector3[]>(ref floats)[0];
-               }
-               public static Vector3 Transform (this Vector3 v, ref Matrix4x4 mat, bool translate = false) {
-                       Vector4 v4 = Vector4.Transform (new Vector4 (v, translate ? 1f : 0f), mat);
-                       return new Vector3 (v4.X, v4.Y, v4.Z);
-               }
-               public static Vector3 ToVector3 (this Vector4 v) {
-                       return Unsafe.As<Vector4, Vector3>(ref v);
-               }
-               public static T[] SubArray<T>(this T[] array, int offset, int length)
-               {
-                       T[] result = new T[length];
-                       Array.Copy(array, offset, result, 0, length);
-                       return result;
-               }
-               #endregion
-
-               // Fixed sub resource on first mip level and layer
-               public static void setImageLayout (
-                       VkCommandBuffer cmdbuffer,
-                       VkImage image,
-                       VkImageAspectFlags aspectMask,
-                       VkImageLayout oldImageLayout,
-                       VkImageLayout newImageLayout,
-                       VkPipelineStageFlags srcStageMask = VkPipelineStageFlags.AllCommands,
-                       VkPipelineStageFlags dstStageMask = VkPipelineStageFlags.AllCommands) {
-                       VkImageSubresourceRange subresourceRange = new VkImageSubresourceRange {
-                               aspectMask = aspectMask,
-                               baseMipLevel = 0,
-                               levelCount = 1,
-                               layerCount = 1,
-                       };
-                       setImageLayout (cmdbuffer, image, aspectMask, oldImageLayout, newImageLayout, subresourceRange);
-               }
-
-               // Create an image memory barrier for changing the layout of
-               // an image and put it into an active command buffer
-               // See chapter 11.4 "Image Layout" for details
-
-               public static void setImageLayout (
-                       VkCommandBuffer cmdbuffer,
-                       VkImage image,
-                       VkImageAspectFlags aspectMask,
-                       VkImageLayout oldImageLayout,
-                       VkImageLayout newImageLayout,
-                       VkImageSubresourceRange subresourceRange,
-                       VkPipelineStageFlags srcStageMask = VkPipelineStageFlags.AllCommands,
-                       VkPipelineStageFlags dstStageMask = VkPipelineStageFlags.AllCommands) {
-                       // Create an image barrier object
-                       VkImageMemoryBarrier imageMemoryBarrier = default;
-                       imageMemoryBarrier.srcQueueFamilyIndex = Vk.QueueFamilyIgnored;
-                       imageMemoryBarrier.dstQueueFamilyIndex = Vk.QueueFamilyIgnored;
-                       imageMemoryBarrier.oldLayout = oldImageLayout;
-                       imageMemoryBarrier.newLayout = newImageLayout;
-                       imageMemoryBarrier.image = image;
-                       imageMemoryBarrier.subresourceRange = subresourceRange;
-
-                       // Source layouts (old)
-                       // Source access mask controls actions that have to be finished on the old layout
-                       // before it will be transitioned to the new layout
-                       switch (oldImageLayout) {
-                               case VkImageLayout.Undefined:
-                                       // Image layout is undefined (or does not matter)
-                                       // Only valid as initial layout
-                                       // No flags required, listed only for completeness
-                                       imageMemoryBarrier.srcAccessMask = 0;
-                                       break;
-
-                               case VkImageLayout.Preinitialized:
-                                       // Image is preinitialized
-                                       // Only valid as initial layout for linear images, preserves memory contents
-                                       // Make sure host writes have been finished
-                                       imageMemoryBarrier.srcAccessMask = VkAccessFlags.HostWrite;
-                                       break;
-
-                               case VkImageLayout.ColorAttachmentOptimal:
-                                       // Image is a color attachment
-                                       // Make sure any writes to the color buffer have been finished
-                                       imageMemoryBarrier.srcAccessMask = VkAccessFlags.ColorAttachmentWrite;
-                                       break;
-
-                               case VkImageLayout.DepthStencilAttachmentOptimal:
-                                       // Image is a depth/stencil attachment
-                                       // Make sure any writes to the depth/stencil buffer have been finished
-                                       imageMemoryBarrier.srcAccessMask = VkAccessFlags.DepthStencilAttachmentWrite;
-                                       break;
-
-                               case VkImageLayout.TransferSrcOptimal:
-                                       // Image is a transfer source
-                                       // Make sure any reads from the image have been finished
-                                       imageMemoryBarrier.srcAccessMask = VkAccessFlags.TransferRead;
-                                       break;
-
-                               case VkImageLayout.TransferDstOptimal:
-                                       // Image is a transfer destination
-                                       // Make sure any writes to the image have been finished
-                                       imageMemoryBarrier.srcAccessMask = VkAccessFlags.TransferWrite;
-                                       break;
-
-                               case VkImageLayout.ShaderReadOnlyOptimal:
-                                       // Image is read by a shader
-                                       // Make sure any shader reads from the image have been finished
-                                       imageMemoryBarrier.srcAccessMask = VkAccessFlags.ShaderRead;
-                                       break;
-                       }
-
-                       // Target layouts (new)
-                       // Destination access mask controls the dependency for the new image layout
-                       switch (newImageLayout) {
-                               case VkImageLayout.TransferDstOptimal:
-                                       // Image will be used as a transfer destination
-                                       // Make sure any writes to the image have been finished
-                                       imageMemoryBarrier.dstAccessMask = VkAccessFlags.TransferWrite;
-                                       break;
-
-                               case VkImageLayout.TransferSrcOptimal:
-                                       // Image will be used as a transfer source
-                                       // Make sure any reads from and writes to the image have been finished
-                                       imageMemoryBarrier.srcAccessMask = imageMemoryBarrier.srcAccessMask | VkAccessFlags.TransferRead;
-                                       imageMemoryBarrier.dstAccessMask = VkAccessFlags.TransferRead;
-                                       break;
-
-                               case VkImageLayout.ColorAttachmentOptimal:
-                                       // Image will be used as a color attachment
-                                       // Make sure any writes to the color buffer have been finished
-                                       imageMemoryBarrier.srcAccessMask = VkAccessFlags.TransferRead;
-                                       imageMemoryBarrier.dstAccessMask = VkAccessFlags.ColorAttachmentWrite;
-                                       break;
-
-                               case VkImageLayout.DepthStencilAttachmentOptimal:
-                                       // Image layout will be used as a depth/stencil attachment
-                                       // Make sure any writes to depth/stencil buffer have been finished
-                                       imageMemoryBarrier.dstAccessMask = imageMemoryBarrier.dstAccessMask | VkAccessFlags.DepthStencilAttachmentWrite;
-                                       break;
-
-                               case VkImageLayout.ShaderReadOnlyOptimal:
-                                       // Image will be read in a shader (sampler, input attachment)
-                                       // Make sure any writes to the image have been finished
-                                       if (imageMemoryBarrier.srcAccessMask == 0) {
-                                               imageMemoryBarrier.srcAccessMask = VkAccessFlags.HostWrite | VkAccessFlags.TransferWrite;
-                                       }
-                                       imageMemoryBarrier.dstAccessMask = VkAccessFlags.ShaderRead;
-                                       break;
-                       }
-
-                       // Put barrier inside setup command buffer
-                       Vk.vkCmdPipelineBarrier (
-                               cmdbuffer,
-                               srcStageMask,
-                               dstStageMask,
-                               0,
-                               0, IntPtr.Zero,
-                               0, IntPtr.Zero,
-                               1, ref imageMemoryBarrier);
-               }
-               /// <summary>
-               /// Find usage flags and aspect flag from image layout
-               /// </summary>
-               public static void QueryLayoutRequirements (VkImageLayout layout, ref VkImageUsageFlags usage, ref VkImageAspectFlags aspectFlags) {
-                       switch (layout) {
-                               case VkImageLayout.ColorAttachmentOptimal:
-                               case VkImageLayout.PresentSrcKHR:
-                               case VkImageLayout.SharedPresentKHR:
-                                       aspectFlags |= VkImageAspectFlags.Color;
-                                       if (usage.HasFlag (VkImageUsageFlags.Sampled))
-                                               usage |= VkImageUsageFlags.InputAttachment;
-                                       usage |= VkImageUsageFlags.ColorAttachment;
-                                       break;
-                               case VkImageLayout.DepthStencilAttachmentOptimal:
-                                       aspectFlags |= VkImageAspectFlags.Depth | VkImageAspectFlags.Stencil;
-                                       usage |= VkImageUsageFlags.DepthStencilAttachment;
-                                       break;
-                               case VkImageLayout.DepthStencilReadOnlyOptimal:
-                                       aspectFlags |= VkImageAspectFlags.Depth | VkImageAspectFlags.Stencil;
-                                       if (usage.HasFlag (VkImageUsageFlags.ColorAttachment))
-                                               usage |= VkImageUsageFlags.InputAttachment;
-                                       else
-                                               usage |= VkImageUsageFlags.Sampled;
-                                       break;
-                               case VkImageLayout.ShaderReadOnlyOptimal:
-                                       aspectFlags |= VkImageAspectFlags.Color;
-                                       usage |= VkImageUsageFlags.Sampled;
-                                       break;
-                               case VkImageLayout.TransferSrcOptimal:
-                                       usage |= VkImageUsageFlags.TransferSrc;
-                                       break;
-                               case VkImageLayout.TransferDstOptimal:
-                                       usage |= VkImageUsageFlags.TransferDst;
-                                       break;
-                               case VkImageLayout.DepthReadOnlyStencilAttachmentOptimalKHR:
-                               case VkImageLayout.DepthAttachmentStencilReadOnlyOptimalKHR:
-                                       aspectFlags |= VkImageAspectFlags.Depth | VkImageAspectFlags.Stencil;
-                                       usage |= VkImageUsageFlags.Sampled | VkImageUsageFlags.DepthStencilAttachment;
-                                       break;
-                       }
-               }
-               /// <summary>
-               /// Try to get the block width and height of a compressed format
-               /// </summary>
-               /// <returns><c>true</c>return true if format given as first argument is a compressed format.</returns>
-               /// <param name="format">Vulkan format to test.</param>
-               /// <param name="width">Compressed block width.</param>
-               /// <param name="height">Compressed block height.</param>
-               public static bool TryGetCompressedFormatBlockSize (this VkFormat format, out uint width, out uint height)
-               {
-                       width = height = 1;
-                       if (format < VkFormat.Bc1RgbUnormBlock || format > (VkFormat)1000066013) //VK_FORMAT_ASTC_12x12_SFLOAT_BLOCK_EXT)
-                               return false;
-                       if (format < VkFormat.Astc5x4UnormBlock)
-                               width = height = 4;
-                       else {
-                               string str = format.ToString ();
-                               if (str.StartsWith ("Astc", StringComparison.OrdinalIgnoreCase)) {
-                                       width = uint.Parse (str.Substring (4, 1));
-                                       height = uint.Parse (str.Substring (6, 1));
-                               }
-                       }
-
-                       return true;
-               }
-               //TODO:quick done list, refine needed
-               public static VkPipelineStageFlags GetDefaultStage (this VkImageLayout layout) {
-                       switch (layout) {
-                       case VkImageLayout.Preinitialized:
-                       case VkImageLayout.Undefined:
-                               return VkPipelineStageFlags.AllCommands;
-
-                       case VkImageLayout.General:
-                               return VkPipelineStageFlags.ComputeShader;
-
-                       case VkImageLayout.ColorAttachmentOptimal:
-                       case VkImageLayout.DepthStencilAttachmentOptimal:
-                               return VkPipelineStageFlags.ColorAttachmentOutput;
-
-                       case VkImageLayout.DepthStencilReadOnlyOptimal:
-                       case VkImageLayout.DepthReadOnlyStencilAttachmentOptimalKHR:
-                       case VkImageLayout.DepthAttachmentStencilReadOnlyOptimalKHR:
-                               return VkPipelineStageFlags.EarlyFragmentTests;
-
-                       case VkImageLayout.ShaderReadOnlyOptimal:
-                               return VkPipelineStageFlags.FragmentShader;
-
-                       case VkImageLayout.TransferSrcOptimal:
-                       case VkImageLayout.TransferDstOptimal:
-                               return VkPipelineStageFlags.Transfer;
-
-                       case VkImageLayout.PresentSrcKHR:
-                       case VkImageLayout.SharedPresentKHR:
-                               return VkPipelineStageFlags.ColorAttachmentOutput;
-
-                       //case VkImageLayout.ShadingRateOptimalNV:
-                       //case VkImageLayout.FragmentDensityMapOptimalEXT:
-                       default:
-                               return VkPipelineStageFlags.AllCommands;
-                       }
-               }
-               public static Matrix4x4 CreatePerspectiveFieldOfView (float fov, float aspectRatio, float zNear, float zFar) {
-                       float f = (float)(1.0 / System.Math.Tan (0.5 * fov));
-                       return new Matrix4x4 (
-                               f / aspectRatio, 0, 0, 0,
-                               0, -f, 0, 0,
-                               0, 0, zFar / (zNear - zFar), -1,
-                               0, 0, zNear * zFar / (zNear - zFar), 0
-                       );
-               }
-
-               public static VkShaderStageFlags ShaderKindToStageFlag (shaderc.ShaderKind shaderKind) {
-                       switch (shaderKind) {
-                       case shaderc.ShaderKind.VertexShader:
-                       case shaderc.ShaderKind.GlslDefaultVertexShader:
-                               return VkShaderStageFlags.Vertex;
-                       case shaderc.ShaderKind.FragmentShader:
-                       case shaderc.ShaderKind.GlslDefaultFragmentShader:
-                               return VkShaderStageFlags.Fragment;
-                       case shaderc.ShaderKind.ComputeShader:
-                       case shaderc.ShaderKind.GlslDefaultComputeShader:
-                               return VkShaderStageFlags.Compute;
-                       case shaderc.ShaderKind.GeometryShader:
-                       case shaderc.ShaderKind.GlslDefaultGeometryShader:
-                               return VkShaderStageFlags.Geometry;
-                       case shaderc.ShaderKind.TessControlShader:
-                       case shaderc.ShaderKind.GlslDefaultTessControlShader:
-                               return VkShaderStageFlags.TessellationControl;
-                       case shaderc.ShaderKind.TessEvaluationShader:
-                       case shaderc.ShaderKind.GlslDefaultTessEvaluationShader:
-                               return VkShaderStageFlags.TessellationEvaluation;
-                       case shaderc.ShaderKind.RaygenShader:
-                       case shaderc.ShaderKind.GlslDefaultRaygenShader:
-                               return VkShaderStageFlags.RaygenKHR;
-                       case shaderc.ShaderKind.AnyhitShader:
-                       case shaderc.ShaderKind.GlslDefaultAnyhitShader:
-                               return VkShaderStageFlags.AnyHitKHR;
-                       case shaderc.ShaderKind.ClosesthitShader:
-                       case shaderc.ShaderKind.GlslDefaultClosesthitShader:
-                               return VkShaderStageFlags.ClosestHitKHR;
-                       case shaderc.ShaderKind.MissShader:
-                       case shaderc.ShaderKind.GlslDefaultMissShader:
-                               return VkShaderStageFlags.MissKHR;
-                       case shaderc.ShaderKind.IntersectionShader:
-                       case shaderc.ShaderKind.GlslDefaultIntersectionShader:
-                               return VkShaderStageFlags.IntersectionKHR;
-                       case shaderc.ShaderKind.CallableShader:
-                       case shaderc.ShaderKind.GlslDefaultCallableShader:
-                               return VkShaderStageFlags.CallableKHR;
-                       case shaderc.ShaderKind.TaskShader:
-                       case shaderc.ShaderKind.GlslDefaultTaskShader:
-                               return VkShaderStageFlags.TaskNV;
-                       case shaderc.ShaderKind.MeshShader:
-                       case shaderc.ShaderKind.GlslDefaultMeshShader:
-                               return VkShaderStageFlags.MeshNV;
-                       default:
-                               throw new NotSupportedException ($"shaderc shaderKind {shaderKind} conversion to VK StageFlag  not handled");
-                       }
-               }
-               public static shaderc.ShaderKind ShaderStageToShaderKind (VkShaderStageFlags stageFlag) {
-                       switch (stageFlag) {
-                       case VkShaderStageFlags.Vertex:
-                               return shaderc.ShaderKind.VertexShader;
-                       case VkShaderStageFlags.TessellationControl:
-                               return shaderc.ShaderKind.TessControlShader;
-                       case VkShaderStageFlags.TessellationEvaluation:
-                               return shaderc.ShaderKind.TessEvaluationShader;
-                       case VkShaderStageFlags.Geometry:
-                               return shaderc.ShaderKind.GeometryShader;
-                       case VkShaderStageFlags.Fragment:
-                               return shaderc.ShaderKind.FragmentShader;
-                       case VkShaderStageFlags.Compute:
-                               return shaderc.ShaderKind.ComputeShader;
-                       case VkShaderStageFlags.RaygenKHR:
-                               return shaderc.ShaderKind.RaygenShader;
-                       case VkShaderStageFlags.AnyHitKHR:
-                               return shaderc.ShaderKind.AnyhitShader;
-                       case VkShaderStageFlags.ClosestHitKHR:
-                               return shaderc.ShaderKind.ClosesthitShader;
-                       case VkShaderStageFlags.MissKHR:
-                               return shaderc.ShaderKind.MissShader;
-                       case VkShaderStageFlags.IntersectionKHR:
-                               return shaderc.ShaderKind.IntersectionShader;
-                       case VkShaderStageFlags.CallableKHR:
-                               return shaderc.ShaderKind.CallableShader;
-                       case VkShaderStageFlags.TaskNV:
-                               return shaderc.ShaderKind.TaskShader;
-                       case VkShaderStageFlags.MeshNV:
-                               return shaderc.ShaderKind.MeshShader;
-                       default:
-                               throw new NotSupportedException ($"Error Shader Stage flag conversion to ShaderKind: {stageFlag}");
-                       }
-               }
-       }
-}