- ktx image loading.
- Memory pools
-### VkWindow class
-
-To create a new vulkan application, derrive your application from `VkWindow`. Validation and
-debug reports may be activated with the static Fields of the `Instance` class.
-
-```csharp
-class Program : VkWindow {
- static void Main (string[] args) {
- Instance.VALIDATION = true;
-
- using (Program vke = new Program ()) {
- vke.Run ();
- }
- }
-}
-```
-
-### Enabling features
-
-Override the `configureEnabledFeatures` method of `VkWindow` to enable features.
-```csharp
-protected override void configureEnabledFeatures (VkPhysicalDeviceFeatures available_features, ref VkPhysicalDeviceFeatures enabled_features) {
- enabled_features.samplerAnisotropy = available_features.samplerAnisotropy;
-}
-```
-### Creating queues
-
-To create queues, override the `createQueues` method of `VkWindow`. This function is called before the logical device creation and will take care of physically available queues, creating duplicates if count exceed availability. The `base` method will create a default presentable queue.
-
-```csharp
-protected override void createQueues () {
- base.createQueues ();
- transferQ = new Queue (dev, VkQueueFlags.Transfer);
-}
-```
-### Rendering
-
-The constructor of the `VkWIndow` will finish the vulkan initialisation, so that you may create pipelines, buffers, and so on in your constructor.
-
-VkWindow will provide the default swapchain, but it's up to you to create the frame buffers. For the triangle example, create them in the `OnResize` override.
-```csharp
-Framebuffer[] frameBuffers;
-
-protected override void OnResize () {
- if (frameBuffers != null)
- for (int i = 0; i < swapChain.ImageCount; ++i)
- frameBuffers[i]?.Dispose ();
- frameBuffers = new Framebuffer[swapChain.ImageCount];
-
- for (int i = 0; i < swapChain.ImageCount; ++i)
- frameBuffers[i] = new Framebuffer (pipeline.RenderPass, swapChain.Width, swapChain.Height,
- (pipeline.Samples == VkSampleCountFlags.SampleCount1) ? new Image[] {
- swapChain.images[i],
- null
- } : new Image[] {
- null,
- null,
- swapChain.images[i]
- });
-
- buildCommandBuffers ();
-}
-```
-
-using System;
+// 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.Diagnostics;
using System.IO;
using Microsoft.Build.Framework;
SwapChain.PREFERED_FORMAT = VkFormat.B8g8r8a8Unorm;
#if DEBUG
Instance.VALIDATION = true;
- Instance.DEBUG_UTILS = true;
Instance.RENDER_DOC_CAPTURE = false;
#endif
using (Program vke = new Program ()) {
static void Main (string[] args) {
#if DEBUG
Instance.VALIDATION = true;
- Instance.DEBUG_UTILS = true;
Instance.RENDER_DOC_CAPTURE = false;
#endif
using (Program vke = new Program ()) {
public Matrix4x4 projection;
public Matrix4x4 view;
public Matrix4x4 model;
- //public Vector4 lightPos;
}
public struct PushConstants {
static void Main (string[] args) {
#if DEBUG
Instance.VALIDATION = true;
- Instance.DEBUG_UTILS = true;
Instance.RENDER_DOC_CAPTURE = true;
#endif
static void Main (string[] args) {
#if DEBUG
Instance.VALIDATION = true;
- Instance.DEBUG_UTILS = true;
Instance.RENDER_DOC_CAPTURE = false;
#endif
using (Program vke = new Program ()) {
--- /dev/null
+
+### VkWindow class
+
+To create a new vulkan application, derrive your application from `VkWindow`. Validation and
+debug reports may be activated with the static Fields of the `Instance` class.
+
+```csharp
+class Program : VkWindow {
+ static void Main (string[] args) {
+ Instance.VALIDATION = true;
+
+ using (Program vke = new Program ()) {
+ vke.Run ();
+ }
+ }
+}
+```
+### Enabling extensions
+
+The `VkWindow` class provides two properties that you may override to enable additional extensions.
+
+### Enabling features
+
+Override the `configureEnabledFeatures` method of `VkWindow` to enable features.
+```csharp
+protected override void configureEnabledFeatures (VkPhysicalDeviceFeatures available_features, ref VkPhysicalDeviceFeatures enabled_features) {
+ enabled_features.samplerAnisotropy = available_features.samplerAnisotropy;
+}
+```
+### Creating queues
+
+To create queues, override the `createQueues` method of `VkWindow`. This function is called before the logical device creation and will take care of physically available queues, creating duplicates if count exceed availability. The `base` method will create a default presentable queue.
+
+```csharp
+protected override void createQueues () {
+ base.createQueues ();
+ transferQ = new Queue (dev, VkQueueFlags.Transfer);
+}
+```
+### Rendering
+
+The constructor of the `VkWIndow` will finish the vulkan initialisation, so that you may create pipelines, buffers, and so on in your constructor.
+
+VkWindow will provide the default swapchain, but it's up to you to create the frame buffers. For the triangle example, create them in the `OnResize` override.
+```csharp
+Framebuffer[] frameBuffers;
+
+protected override void OnResize () {
+ if (frameBuffers != null)
+ for (int i = 0; i < swapChain.ImageCount; ++i)
+ frameBuffers[i]?.Dispose ();
+ frameBuffers = new Framebuffer[swapChain.ImageCount];
+
+ for (int i = 0; i < swapChain.ImageCount; ++i)
+ frameBuffers[i] = new Framebuffer (pipeline.RenderPass, swapChain.Width, swapChain.Height,
+ (pipeline.Samples == VkSampleCountFlags.SampleCount1) ? new Image[] {
+ swapChain.images[i],
+ null
+ } : new Image[] {
+ null,
+ null,
+ swapChain.images[i]
+ });
+
+ buildCommandBuffers ();
+}
+```
+
// 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.Numerics;
using System.Runtime.InteropServices;
using vke;
static void Main (string[] args) {
#if DEBUG
Instance.VALIDATION = true;
- Instance.DEBUG_UTILS = true;
Instance.RENDER_DOC_CAPTURE = false;
#endif
ushort[] indices = new ushort[] { 0, 1, 2 };
Program () : base () {
-
cmds = cmdPool.AllocateCommandBuffer(swapChain.ImageCount);
vbo = new HostBuffer<Vertex> (dev, VkBufferUsageFlags.VertexBuffer, vertices);
}
void crow_thread_func () {
- vkvgDev = new vkvg.Device (instance.Handle, phy.Handle, dev.Handle, presentQueue.qFamIndex,
+ vkvgDev = new vkvg.Device (instance.Handle, phy.Handle, dev.VkDev.Handle, presentQueue.qFamIndex,
vkvg.SampleCount.Sample_4, presentQueue.index);
crow = new Interface (vkvgDev, (int)swapChain.Width, (int)swapChain.Height);
static void Main (string[] args) {
#if DEBUG
Instance.VALIDATION = true;
- Instance.DEBUG_UTILS = true;
//Instance.RENDER_DOC_CAPTURE = false;
#endif
SwapChain.PREFERED_FORMAT = VkFormat.B8g8r8a8Srgb;
}
}
+ public override string[] EnabledInstanceExtensions => new string[] {
+ Ext.I.VK_EXT_debug_utils
+ };
+
public override string[] EnabledDeviceExtensions => new string[] {
Ext.D.VK_KHR_swapchain,
Ext.D.VK_EXT_debug_marker
DescriptorPool descriptorPool;
DescriptorSet descriptorSet;
+ vke.DebugUtils.Messenger dbgmsg;
+
+ Deferred () : base("deferred") {
+ dbgmsg = new vke.DebugUtils.Messenger (instance, VkDebugUtilsMessageTypeFlagsEXT.PerformanceEXT | VkDebugUtilsMessageTypeFlagsEXT.ValidationEXT | VkDebugUtilsMessageTypeFlagsEXT.GeneralEXT,
+ VkDebugUtilsMessageSeverityFlagsEXT.InfoEXT |
+ VkDebugUtilsMessageSeverityFlagsEXT.WarningEXT |
+ VkDebugUtilsMessageSeverityFlagsEXT.ErrorEXT |
+ VkDebugUtilsMessageSeverityFlagsEXT.VerboseEXT);
- Deferred () : base("deferred") {
camera = new Camera (Utils.DegreesToRadians (45f), 1f, 0.1f, 16f);
camera.SetPosition (0, 0, 2);
#endregion
protected override void Dispose (bool disposing) {
+ dev.WaitIdle ();
if (disposing) {
if (!isDisposed) {
computeCmdPool.Dispose ();
plBlur.Dispose ();
plToneMap.Dispose ();
descriptorPool.Dispose ();
+ dbgmsg.Dispose ();
}
dev.DestroySemaphore (blurComplete);
}
static void Main (string[] args) {
#if DEBUG
Instance.VALIDATION = true;
- Instance.DEBUG_UTILS = true;
Instance.RENDER_DOC_CAPTURE = false;
#endif
using (Program vke = new Program ()) {
/// </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) {
+ 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 ();
- }
- /// <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);
}
public static IntPtr Pin<T> (this List<T> obj) {
if (handles.ContainsKey (obj))
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 List<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
#region DebugMarkers
using System.Runtime.InteropServices;
using System.Text;
-namespace Vulkan
-{
- public class FixedUtf8String : IDisposable
- {
- GCHandle _handle;
- uint _numBytes;
-
- public IntPtr Ptr => _handle.AddrOfPinnedObject();
-
- public FixedUtf8String(string s)
- {
- if (s == null)
- {
- throw new ArgumentNullException(nameof(s));
- }
-
- byte[] text = Encoding.UTF8.GetBytes(s + "\0");
- _handle = GCHandle.Alloc(text, GCHandleType.Pinned);
- _numBytes = (uint)text.Length;
- }
-
- public void SetText(string s)
- {
- if (s == null)
- {
- throw new ArgumentNullException(nameof(s));
- }
-
- _handle.Free();
- byte[] text = Encoding.UTF8.GetBytes(s);
- _handle = GCHandle.Alloc(text, GCHandleType.Pinned);
- _numBytes = (uint)text.Length;
- }
-
- private string GetString()
- {
- return Marshal.PtrToStringUni(Ptr);
- }
-
- public static implicit operator IntPtr (FixedUtf8String utf8String) => utf8String.Ptr;
- public static implicit operator FixedUtf8String(string s) => new FixedUtf8String(s);
- public static implicit operator string(FixedUtf8String utf8String) => utf8String.GetString();
-
- #region IDisposable Support
- private bool disposedValue = false; // Pour détecter les appels redondants
-
- protected virtual void Dispose (bool disposing) {
- if (!disposedValue) {
- if (disposing) {
- // TODO: supprimer l'état managé (objets managés).
- }
-
- // TODO: libérer les ressources non managées (objets non managés) et remplacer un finaliseur ci-dessous.
- // TODO: définir les champs de grande taille avec la valeur Null.
- _handle.Free ();
- disposedValue = true;
- }
- }
-
- // TODO: remplacer un finaliseur seulement si la fonction Dispose(bool disposing) ci-dessus a du code pour libérer les ressources non managées.
- ~FixedUtf8String() {
- // Ne modifiez pas ce code. Placez le code de nettoyage dans Dispose(bool disposing) ci-dessus.
- Dispose(false);
- }
-
- // Ce code est ajouté pour implémenter correctement le modèle supprimable.
- public void Dispose () {
- // Ne modifiez pas ce code. Placez le code de nettoyage dans Dispose(bool disposing) ci-dessus.
- Dispose (true);
- // TODO: supprimer les marques de commentaire pour la ligne suivante si le finaliseur est remplacé ci-dessus.
- GC.SuppressFinalize(this);
- }
- #endregion
- }
+namespace Vulkan {
+ public class FixedUtf8String : IDisposable {
+ GCHandle handle;
+ readonly uint numBytes;
+
+ public IntPtr Ptr => handle.AddrOfPinnedObject ();
+
+ public FixedUtf8String (string s) {
+ if (s == null)
+ throw new ArgumentNullException (nameof (s));
+
+ byte[] text = Encoding.UTF8.GetBytes (s + "\0");
+ handle = GCHandle.Alloc (text, GCHandleType.Pinned);
+ numBytes = (uint)text.Length;
+ }
+
+ private string GetString () {
+ return Marshal.PtrToStringUni (Ptr);
+ }
+
+ public static implicit operator IntPtr (FixedUtf8String utf8String) => utf8String.Ptr;
+ public static implicit operator FixedUtf8String (string s) => new FixedUtf8String (s);
+ public static implicit operator string (FixedUtf8String utf8String) => utf8String.GetString ();
+
+ #region IDisposable Support
+ private bool disposedValue = false; // Pour détecter les appels redondants
+
+ protected virtual void Dispose (bool disposing) {
+ if (!disposedValue) {
+ handle.Free ();
+ disposedValue = true;
+ }
+ }
+ ~FixedUtf8String () {
+ Dispose (false);
+ }
+ public void Dispose () {
+ Dispose (true);
+ GC.SuppressFinalize (this);
+ }
+ #endregion
+ }
}
\ No newline at end of file
public MarshaledObject (T mobj) {
handle = GCHandle.Alloc (mobj, GCHandleType.Pinned);
}
-
- void freeHandle () {
- if (!disposed)
- handle.Free ();
- disposed = true;
+ ~MarshaledObject () {
+ handle.Free ();
}
-
- #region IDisposable Support
- private bool disposed;
-
- ~MarshaledObject() {
- freeHandle ();
- }
-
- public void Dispose () {
- freeHandle ();
- GC.SuppressFinalize(this);
- }
- #endregion
+ public void Dispose () {
+ handle.Free ();
+ GC.SuppressFinalize (this);
+ }
}
}
namespace vke {
#if MEMORY_POOLS
+ /// Direct how memory is allocated by a MemoryPool.
public enum MemoryPoolType {
+ /// Not yet implemented.
Random,
- Linear
+ /// First free space next to the last added ressource will be choosen.
+ Linear
}
/// <summary>
/// A memory pool is a single chunck of memory of a kind shared among multiple resources.
Device dev;
internal VkDeviceMemory vkMemory;
VkMemoryAllocateInfo memInfo = VkMemoryAllocateInfo.New ();
-
- //Resource firstResource;
+ readonly ulong bufferImageGranularity;
Resource lastResource;
- //Resource mappedFrom;
- //Resource mappedTo;
-
- //ulong freeMemPointer;
IntPtr mappedPointer;
-
+ /// Allocated device size in byte.
public ulong Size => memInfo.allocationSize;
+ /// Return true if pool memory is currently mapped.
public bool IsMapped => mappedPointer != IntPtr.Zero;
+ /// Return mapped memory pointer or null if not mapped.
public IntPtr MappedData => mappedPointer;
- public Resource Last => lastResource;
+ /// Last added resource, this is the entry element for the double linked list of ressource.
+ public Resource Last => lastResource;
/// <summary>
- /// Initializes a new instance of the <see cref="T:CVKL.MemoryPool"/> class.
+ /// Initializes a new instance of the <see cref="T:vke.MemoryPool"/> class.
/// </summary>
- /// <param name="dev">device</param>
+ /// <param name="dev">The vulkan device instance associated with this memory pool.</param>
/// <param name="memoryTypeIndex">Memory type index.</param>
/// <param name="size">Size</param>
public MemoryPool (Device dev, uint memoryTypeIndex, UInt64 size) {
this.dev = dev;
+ bufferImageGranularity = dev.phy.Limits.bufferImageGranularity;
memInfo.allocationSize = size;
memInfo.memoryTypeIndex = memoryTypeIndex;
Utils.CheckResult (vkAllocateMemory (dev.VkDev, ref memInfo, IntPtr.Zero, out vkMemory));
}
-
+ /// <summary>
+ /// Allocate memory for a new resource in this memory pool.
+ /// </summary>
+ /// <param name="resource">An <see cref="T:vke.Image"/> or a <see cref="T:vke.Buffer"/> ressource.</param>
public void Add (Resource resource) {
resource.memoryPool = this;
do {
offset = previous.poolOffset + previous.AllocatedDeviceMemorySize;
- if (previous.IsLinar != resource.IsLinar && offset % dev.BufferImageGranularity > 0)
- offset += dev.BufferImageGranularity - (offset % dev.BufferImageGranularity);
+ if (previous.IsLinar != resource.IsLinar && offset % bufferImageGranularity > 0)
+ offset += bufferImageGranularity - (offset % bufferImageGranularity);
if (offset % resource.MemoryAlignment > 0)
offset += resource.MemoryAlignment - (offset % resource.MemoryAlignment);
resource.bindMemory ();
}
-
+ /// <summary>
+ /// Try to reorganize ressources in this pool to optimize memory usage.
+ /// </summary>
public void Defrag () {
throw new NotImplementedException ();
}
-
+ /// <summary>
+ /// Remove the specified resource.
+ /// </summary>
+ /// <param name="resource">Resource.</param>
public void Remove (Resource resource) {
if (resource == lastResource)
lastResource = resource.previous;
}
}
resource.next = resource.previous = null;
- }
+ }/// <summary>
+ /// Map the pool's memory at the specified offset.
+ /// </summary>
+ /// <param name="size">Size.</param>
+ /// <param name="offset">Offset.</param>
public void Map (ulong size = Vk.WholeSize, ulong offset = 0) {
Utils.CheckResult (vkMapMemory (dev.VkDev, vkMemory, offset, size, 0, ref mappedPointer));
}
+ /// <summary>
+ /// Unmap previously mapped memory of this pool.
+ /// </summary>
public void Unmap () {
vkUnmapMemory (dev.VkDev, vkMemory);
mappedPointer = IntPtr.Zero;
}
-#region IDisposable Support
+ #region IDisposable Support
private bool disposedValue;
protected virtual void Dispose (bool disposing) {
Dispose (true);
GC.SuppressFinalize(this);
}
-#endregion
+ #endregion
}
#endif
}
\ No newline at end of file
--- /dev/null
+// 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 vke {
+ /// <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);
+ }
+ }
+}
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;
+++ /dev/null
-namespace Vulkan
-{
- public struct Version
- {
- private readonly uint value;
-
- public Version(uint major, uint minor, uint patch)
- {
- value = major << 22 | minor << 12 | patch;
- }
-
- public uint Major => value >> 22;
-
- public uint Minor => (value >> 12) & 0x3ff;
-
- public uint Patch => (value >> 22) & 0xfff;
-
- public static implicit operator uint(Version version)
- {
- return version.value;
- }
- }
-}
\ No newline at end of file
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
+using System.Runtime.InteropServices;
using Glfw;
using Vulkan;
using static Vulkan.Vk;
static Dictionary<IntPtr,VkWindow> windows = new Dictionary<IntPtr, VkWindow>();
IntPtr hWin;
-
+ /**Vulkan Surface */
protected VkSurfaceKHR hSurf;
- protected Instance instance;
- protected PhysicalDevice phy;
+ /**vke Instance encapsulating a VkInstance. */
+ protected Instance instance;
+ /**vke Physical device associated with this window*/
+ protected PhysicalDevice phy;
protected Device dev;
protected PresentQueue presentQueue;
protected SwapChain swapChain;
protected CommandBuffer[] cmds;
protected VkSemaphore[] drawComplete;
- DebugReport dbgRepport;
-
protected uint fps;
protected bool updateViewRequested = true;
protected double lastMouseX, lastMouseY;
Stopwatch frameChrono;
/// <summary>
- /// Override this property to change the list of enabled extensions
+ /// Override this property to change the list of enabled instance extensions
+ /// </summary>
+ public virtual string[] EnabledInstanceExtensions => null;
+
+ /// <summary>
+ /// Override this property to change the list of enabled device extensions
/// </summary>
public virtual string[] EnabledDeviceExtensions => new string[] { Ext.D.VK_KHR_swapchain };
}
void initVulkan (bool vSync) {
- instance = new Instance ();
-
- if (Instance.DEBUG_UTILS) {
- //dbgmsg = new CVKL.DebugUtils.Messenger (instance);
- dbgRepport = new DebugReport (instance,
- VkDebugReportFlagsEXT.ErrorEXT
- | VkDebugReportFlagsEXT.WarningEXT
- | VkDebugReportFlagsEXT.PerformanceWarningEXT
- );
- }
+ List<string> instExts = new List<string> (Glfw3.GetRequiredInstanceExtensions ());
+ if (EnabledInstanceExtensions != null)
+ instExts.AddRange (EnabledInstanceExtensions);
+
+ instance = new Instance (instExts.ToArray());
hSurf = instance.CreateSurface (hWin);
- phy = instance.GetAvailablePhysicalDevice ().Where (p => p.HasSwapChainSupport).FirstOrDefault ();
+ phy = instance.GetAvailablePhysicalDevice ().FirstOrDefault (p => p.HasSwapChainSupport);
- VkPhysicalDeviceFeatures enabledFeatures = default (VkPhysicalDeviceFeatures);
+ VkPhysicalDeviceFeatures enabledFeatures = default;
configureEnabledFeatures (phy.Features, ref enabledFeatures);
//First create the c# device class
cmdPool.SetName ("main CmdPool");
}
/// <summary>
- /// override this method to modify enabled features before device creation
+ /// Override this method to modify enabled features before device creation. Feature availability is given by the first argument.
/// </summary>
- /// <param name="enabled_features">Features.</param>
+ /// <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 create additional queue. Dedicated queue of the requested type will be selected first, created queues may excess
+ /// 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>
protected virtual void createQueues () {
if (disposing) {
cmdPool.Dispose ();
dev.Dispose ();
- dbgRepport?.Dispose ();
instance.Dispose ();
} else
Debug.WriteLine ("a VkWindow has not been correctly disposed");
IntPtr dstStageMask = Marshal.AllocHGlobal (sizeof(uint));
Marshal.WriteInt32 (dstStageMask, (int)VkPipelineStageFlags.ColorAttachmentOutput);
- submit_info.pWaitDstStageMask = dstStageMask;
- if (signal != VkSemaphore.Null) {
- submit_info.signalSemaphoreCount = 1;
- submit_info.pSignalSemaphores = signal.Pin();
- }
- if (wait != VkSemaphore.Null) {
- submit_info.waitSemaphoreCount = 1;
- submit_info.pWaitSemaphores = wait.Pin();
- }
-
- submit_info.commandBufferCount = 1;
- submit_info.pCommandBuffers = handle.Pin();
-
- Utils.CheckResult (vkQueueSubmit (queue, 1, ref submit_info, fence));
-
- if (signal != VkSemaphore.Null)
- signal.Unpin ();
- if (wait != VkSemaphore.Null)
- wait.Unpin ();
- handle.Unpin ();
-
+ using (PinnedObjects pctx = new PinnedObjects ()) {
+ submit_info.pWaitDstStageMask = dstStageMask;
+ if (signal != VkSemaphore.Null) {
+ submit_info.signalSemaphoreCount = 1;
+ submit_info.pSignalSemaphores = signal.Pin (pctx);
+ }
+ if (wait != VkSemaphore.Null) {
+ submit_info.waitSemaphoreCount = 1;
+ submit_info.pWaitSemaphores = wait.Pin (pctx);
+ }
+
+ submit_info.commandBufferCount = 1;
+ submit_info.pCommandBuffers = handle.Pin (pctx);
+
+ Utils.CheckResult (vkQueueSubmit (queue, 1, ref submit_info, fence));
+ }
Marshal.FreeHGlobal (dstStageMask);
}
public void Start (VkCommandBufferUsageFlags usage = 0) {
-//
-// DebugReport.cs
+// Copyright (c) 2019 Jean-Philippe Bruyère <jp_bruyere@hotmail.com>
//
-// Author:
-// Jean-Philippe Bruyère <jp_bruyere@hotmail.com>
-//
-// Copyright (c) 2019 jp
-//
-// Permission is hereby granted, free of charge, to any person obtaining a copy
-// of this software and associated documentation files (the "Software"), to deal
-// in the Software without restriction, including without limitation the rights
-// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
-// copies of the Software, and to permit persons to whom the Software is
-// furnished to do so, subject to the following conditions:
-//
-// The above copyright notice and this permission notice shall be included in
-// all copies or substantial portions of the Software.
-//
-// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
-// THE SOFTWARE.
+// This code is licensed under the MIT license (MIT) (http://opensource.org/licenses/MIT)
using System;
using System.Runtime.InteropServices;
using Vulkan;
using static Vulkan.Vk;
namespace vke {
-
+ [Obsolete("Use the new VK_EXT_debug_utils extension")]
public class DebugReport : IDisposable {
VkDebugReportCallbackEXT handle;
Instance inst;
using static Vulkan.Vk;
namespace vke.DebugUtils {
-
- public class Messenger : IDisposable {
+ /// <summary>
+ /// Dispoable vke class that encapsulate a VkDebugUtilsMessengerEXT object
+ /// </summary>
+ public class Messenger : IDisposable {
Instance inst;
- VkDebugUtilsMessengerEXT handle;
- PFN_vkDebugUtilsMessengerCallbackEXT onMessage = new PFN_vkDebugUtilsMessengerCallbackEXT(HandlePFN_vkDebugUtilsMessengerCallbackEXT);
+ readonly VkDebugUtilsMessengerEXT handle;
+ readonly static PFN_vkDebugUtilsMessengerCallbackEXT onMessage = new PFN_vkDebugUtilsMessengerCallbackEXT(HandlePFN_vkDebugUtilsMessengerCallbackEXT);
static VkBool32 HandlePFN_vkDebugUtilsMessengerCallbackEXT (VkDebugUtilsMessageSeverityFlagsEXT messageSeverity, VkDebugUtilsMessageTypeFlagsEXT messageTypes, IntPtr pCallbackData, IntPtr pUserData) {
- //Console.WriteLine ("{0} {1}: {2}",messageSeverity, messageTypes, Marshal.PtrToStringAnsi(pUserData));
- Console.WriteLine ("MESSAGE RECEIVED");
- return false;
- }
-
-
-
- // PFN_vkDebugReportCallbackEXT debugCallbackDelegate = new PFN_vkDebugReportCallbackEXT (debugCallback);
+ VkDebugUtilsMessengerCallbackDataEXT data = Marshal.PtrToStructure<VkDebugUtilsMessengerCallbackDataEXT> (pCallbackData);
+ ConsoleColor curColor = Console.ForegroundColor;
- // static VkBool32 debugCallback (VkDebugReportFlagsEXT flags, VkDebugReportObjectTypeEXT objectType, ulong obj,
- // UIntPtr location, int messageCode, IntPtr pLayerPrefix, IntPtr pMessage, IntPtr pUserData) {
- // string prefix = "";
- // switch (flags) {
- // case 0:
- // prefix = "?";
- // break;
- // case VkDebugReportFlagsEXT.InformationEXT:
- // Console.ForegroundColor = ConsoleColor.Gray;
- // prefix = "INFO";
- // break;
- // case VkDebugReportFlagsEXT.WarningEXT:
- // Console.ForegroundColor = ConsoleColor.DarkYellow;
- // prefix = "WARN";
- // break;
- // case VkDebugReportFlagsEXT.PerformanceWarningEXT:
- // Console.ForegroundColor = ConsoleColor.Yellow;
- // prefix = "PERF";
- // break;
- // case VkDebugReportFlagsEXT.ErrorEXT:
- // Console.ForegroundColor = ConsoleColor.DarkRed;
- // prefix = "EROR";
- // break;
- // case VkDebugReportFlagsEXT.DebugEXT:
- // Console.ForegroundColor = ConsoleColor.Red;
- // prefix = "DBUG";
- // break;
- // }
+ switch (messageSeverity) {
+ case VkDebugUtilsMessageSeverityFlagsEXT.VerboseEXT:
+ Console.ForegroundColor = ConsoleColor.White;
+ break;
+ case VkDebugUtilsMessageSeverityFlagsEXT.InfoEXT:
+ Console.ForegroundColor = ConsoleColor.DarkCyan;
+ break;
+ case VkDebugUtilsMessageSeverityFlagsEXT.WarningEXT:
+ Console.ForegroundColor = ConsoleColor.DarkYellow;
+ break;
+ case VkDebugUtilsMessageSeverityFlagsEXT.ErrorEXT:
+ Console.ForegroundColor = ConsoleColor.Red;
+ break;
+ }
- // Console.WriteLine ("{0} {1}: {2}",prefix, messageCode, Marshal.PtrToStringAnsi(pMessage));
- //Console.ForegroundColor = ConsoleColor.White;
- // return VkBool32.False;
- //}
-
- public Messenger (Instance instance,
- VkDebugUtilsMessageTypeFlagsEXT typeMask = VkDebugUtilsMessageTypeFlagsEXT.ValidationEXT,
- VkDebugUtilsMessageSeverityFlagsEXT severityMask = VkDebugUtilsMessageSeverityFlagsEXT.ErrorEXT | VkDebugUtilsMessageSeverityFlagsEXT.WarningEXT) {
+ switch (messageTypes) {
+ case VkDebugUtilsMessageTypeFlagsEXT.GeneralEXT:
+ Console.Write ("GEN:");
+ break;
+ case VkDebugUtilsMessageTypeFlagsEXT.PerformanceEXT:
+ Console.Write ("PERF:");
+ break;
+ }
+ Console.WriteLine (Marshal.PtrToStringAnsi (data.pMessage));
+ Console.ForegroundColor = curColor;
+ return false;
+ }
+ /// <summary>
+ /// Create a new debug utils messenger providing a PFN_vkDebugUtilsMessengerCallbackEXT delegate.
+ /// </summary>
+ /// <param name="instance">Vulkan Instance.</param>
+ /// <param name="onMessageDelegate">Message callback.</param>
+ /// <param name="typeMask">Type mask.</param>
+ /// <param name="severityMask">Severity mask.</param>
+ public Messenger (Instance instance, PFN_vkDebugUtilsMessengerCallbackEXT onMessageDelegate,
+ VkDebugUtilsMessageTypeFlagsEXT typeMask =
+ VkDebugUtilsMessageTypeFlagsEXT.ValidationEXT,
+ VkDebugUtilsMessageSeverityFlagsEXT severityMask =
+ VkDebugUtilsMessageSeverityFlagsEXT.ErrorEXT |
+ VkDebugUtilsMessageSeverityFlagsEXT.WarningEXT) {
inst = instance;
VkDebugUtilsMessengerCreateInfoEXT info = VkDebugUtilsMessengerCreateInfoEXT.New ();
info.messageType = typeMask;
info.messageSeverity = severityMask;
- info.pfnUserCallback = Marshal.GetFunctionPointerForDelegate (onMessage);
+ info.pfnUserCallback = Marshal.GetFunctionPointerForDelegate (onMessageDelegate);
info.pUserData = IntPtr.Zero;
Utils.CheckResult (vkCreateDebugUtilsMessengerEXT (inst.VkInstance, ref info, IntPtr.Zero, out handle));
+ }
+ /// <summary>
+ /// Create a new debug utils messenger with default message callback outputing to Console.
+ /// </summary>
+ /// <param name="instance">Vulkan Instance.</param>
+ /// <param name="typeMask">Type mask.</param>
+ /// <param name="severityMask">Severity mask.</param>
+ public Messenger (Instance instance,
+ VkDebugUtilsMessageTypeFlagsEXT typeMask =
+ VkDebugUtilsMessageTypeFlagsEXT.ValidationEXT,
+ VkDebugUtilsMessageSeverityFlagsEXT severityMask =
+ VkDebugUtilsMessageSeverityFlagsEXT.ErrorEXT |
+ VkDebugUtilsMessageSeverityFlagsEXT.WarningEXT) : this (instance, onMessage, typeMask, severityMask) {
}
#region IDisposable Support
/// execute the descriptors writes targeting descriptorSets setted on AddWriteInfo call
/// </summary>
public void Write (Device dev, params object[] descriptors) {
- //if (descriptors.Length != WriteDescriptorSets.Count)
- // throw new Exception ("descriptors count must equal the WriteInfo count.");
- List<object> descriptorsLists = new List<object> ();//strore temp arrays of pDesc for unpinning
- //if descriptorCount>1
- int i = 0;
- int wdsPtr = 0;
- while (i < descriptors.Length) {
- int firstDescriptor = i;
- VkWriteDescriptorSet wds = WriteDescriptorSets[wdsPtr];
- if (dstSetOverride != null)
- wds.dstSet = dstSetOverride.Value.Handle;
- IntPtr pDescriptors = IntPtr.Zero;
+ using (PinnedObjects pinCtx = new PinnedObjects ()) {
+ int i = 0;
+ int wdsPtr = 0;
+ while (i < descriptors.Length) {
+ int firstDescriptor = i;
+ VkWriteDescriptorSet wds = WriteDescriptorSets[wdsPtr];
+ if (dstSetOverride != null)
+ wds.dstSet = dstSetOverride.Value.Handle;
+ IntPtr pDescriptors = IntPtr.Zero;
- if (wds.descriptorCount > 1) {
- List<IntPtr> descPtrArray = new List<IntPtr> ();
- for (int d = 0; d < wds.descriptorCount; d++) {
- descPtrArray.Add (descriptors[i].Pin ());
+ if (wds.descriptorCount > 1) {
+ List<IntPtr> descPtrArray = new List<IntPtr> ();
+ for (int d = 0; d < wds.descriptorCount; d++) {
+ descPtrArray.Add (descriptors[i].Pin (pinCtx));
+ i++;
+ }
+ pDescriptors = descPtrArray.Pin (pinCtx);
+ } else {
+ pDescriptors = descriptors[i].Pin (pinCtx);
i++;
}
- descriptorsLists.Add (descPtrArray);
- pDescriptors = descPtrArray.Pin ();
- } else {
- pDescriptors = descriptors[i].Pin ();
- i++;
+ if (descriptors[firstDescriptor] is VkDescriptorBufferInfo)
+ wds.pBufferInfo = pDescriptors;
+ else if (descriptors[firstDescriptor] is VkDescriptorImageInfo)
+ wds.pImageInfo = pDescriptors;
+
+ WriteDescriptorSets[wdsPtr] = wds;
+ wdsPtr++;
}
- if (descriptors[firstDescriptor] is VkDescriptorBufferInfo)
- wds.pBufferInfo = pDescriptors;
- else if (descriptors[firstDescriptor] is VkDescriptorImageInfo)
- wds.pImageInfo = pDescriptors;
+ vkUpdateDescriptorSets (dev.VkDev, (uint)WriteDescriptorSets.Count, WriteDescriptorSets.Pin (pinCtx), 0, IntPtr.Zero);
+ }
+ }
+ /// <summary>
+ /// execute the descriptors writes targeting descriptorSets setted on AddWriteInfo call
+ /// </summary>
+ public void Push (CommandBuffer cmd, PipelineLayout plLayout, params object[] descriptors) {
+ using (PinnedObjects pinCtx = new PinnedObjects ()) {
+ int i = 0;
+ int wdsPtr = 0;
+ while (i < descriptors.Length) {
+ int firstDescriptor = i;
+ VkWriteDescriptorSet wds = WriteDescriptorSets[wdsPtr];
+ wds.dstSet = 0;
+ IntPtr pDescriptors = IntPtr.Zero;
- WriteDescriptorSets[wdsPtr] = wds;
- wdsPtr++;
+ if (wds.descriptorCount > 1) {
+ List<IntPtr> descPtrArray = new List<IntPtr> ();
+ for (int d = 0; d < wds.descriptorCount; d++) {
+ descPtrArray.Add (descriptors[i].Pin (pinCtx));
+ i++;
+ }
+ pDescriptors = descPtrArray.Pin (pinCtx);
+ } else {
+ pDescriptors = descriptors[i].Pin (pinCtx);
+ i++;
+ }
+ if (descriptors[firstDescriptor] is VkDescriptorBufferInfo)
+ wds.pBufferInfo = pDescriptors;
+ else if (descriptors[firstDescriptor] is VkDescriptorImageInfo)
+ wds.pImageInfo = pDescriptors;
+
+ WriteDescriptorSets[wdsPtr] = wds;
+ wdsPtr++;
+ }
+ vkCmdPushDescriptorSetKHR (cmd.Handle, VkPipelineBindPoint.Graphics, plLayout.handle, 0,
+ (uint)WriteDescriptorSets.Count, WriteDescriptorSets.Pin (pinCtx));
}
- vkUpdateDescriptorSets (dev.VkDev, (uint)WriteDescriptorSets.Count, WriteDescriptorSets.Pin (), 0, IntPtr.Zero);
- WriteDescriptorSets.Unpin ();
- foreach (object descArray in descriptorsLists)
- descArray.Unpin ();
- for (i = 0; i < descriptors.Length; i++)
- descriptors[i].Unpin ();
}
}
+
/// <summary>
/// Descriptor set writes include descriptor in write addition with IDisposable model
/// </summary>
-//
-// Device.cs
+// Copyright (c) 2019 Jean-Philippe Bruyère <jp_bruyere@hotmail.com>
//
-// Author:
-// Jean-Philippe Bruyère <jp_bruyere@hotmail.com>
-//
-// Copyright (c) 2019 jp
-//
-// Permission is hereby granted, free of charge, to any person obtaining a copy
-// of this software and associated documentation files (the "Software"), to deal
-// in the Software without restriction, including without limitation the rights
-// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
-// copies of the Software, and to permit persons to whom the Software is
-// furnished to do so, subject to the following conditions:
-//
-// The above copyright notice and this permission notice shall be included in
-// all copies or substantial portions of the Software.
-//
-// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
-// THE SOFTWARE.
+// This code is licensed under the MIT license (MIT) (http://opensource.org/licenses/MIT)
using System;
-using System.Collections;
using System.Collections.Generic;
using System.IO;
using System.Linq;
/// after being disposed.
/// </summary>
public class Device : IDisposable {
- public readonly PhysicalDevice phy;
+ public readonly PhysicalDevice phy; /**Vulkan physical device class*/
VkDevice dev;
- public VkDevice VkDev => dev;
- public IntPtr Handle => dev.Handle;
- public readonly ulong BufferImageGranularity;
+ public VkDevice VkDev => dev; /**Vulkan logical device handle*/
+
internal List<Queue> queues = new List<Queue> ();
internal bool debugMarkersEnabled;
public Device (PhysicalDevice _phy) {
phy = _phy;
- BufferImageGranularity = phy.Limits.bufferImageGranularity;
}
public void Activate (VkPhysicalDeviceFeatures enabledFeatures, params string[] extensions) {
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 |= VkAccessFlags.TransferRead;
+ //imageMemoryBarrier.srcAccessMask |= VkAccessFlags.TransferRead;
imageMemoryBarrier.dstAccessMask = VkAccessFlags.TransferRead;
break;
// THE SOFTWARE.
using System;
using System.Collections.Generic;
+using System.Linq;
using System.Runtime.InteropServices;
using Vulkan;
using static Vulkan.Vk;
/// <summary>
/// Vulkan Instance disposable class
/// </summary>
- public class Instance : IDisposable {
+ public class Instance : IDisposable {
/// <summary>If true, the VK_LAYER_KHRONOS_validation layer is loaded at startup; </summary>
public static bool VALIDATION;
- /// <summary>If true, the VK_EXT_debug_utils and VK_EXT_debug_report instance extensions are enabled</summary>
- public static bool DEBUG_UTILS;
/// <summary>If true, the VK_LAYER_RENDERDOC_Capture layer is loaded at startup; </summary>
public static bool RENDER_DOC_CAPTURE;
- VkInstance inst;
+ public static uint VK_MAJOR = 1;
+ public static uint VK_MINOR = 1;
+
+ public static string ENGINE_NAME = "vke.net";
+ public static string APPLICATION_NAME = "vke.net";
+
+ VkInstance inst;
public IntPtr Handle => inst.Handle;
public VkInstance VkInstance => inst;
static class Strings {
- public static FixedUtf8String Name = "VKENGINE";
- public static FixedUtf8String VK_KHR_SURFACE_EXTENSION_NAME = "VK_KHR_surface";
- public static FixedUtf8String VK_KHR_WIN32_SURFACE_EXTENSION_NAME = "VK_KHR_win32_surface";
- public static FixedUtf8String VK_KHR_XCB_SURFACE_EXTENSION_NAME = "VK_KHR_xcb_surface";
- public static FixedUtf8String VK_KHR_XLIB_SURFACE_EXTENSION_NAME = "VK_KHR_xlib_surface";
- public static FixedUtf8String VK_KHR_SWAPCHAIN_EXTENSION_NAME = "VK_KHR_swapchain";
- public static FixedUtf8String VK_EXT_DEBUG_REPORT_EXTENSION_NAME = "VK_EXT_debug_report";
- public static FixedUtf8String VK_EXT_DEBUG_UTILS_EXTENSION_NAME = "VK_EXT_debug_utils";
- public static FixedUtf8String LayerValidation = "VK_LAYER_KHRONOS_validation";
- public static FixedUtf8String LayerValidation_old = "VK_LAYER_LUNARG_standard_validation";
- public static FixedUtf8String LayerMonitor = "VK_LAYER_LUNARG_monitor";
- public static FixedUtf8String VkTraceLayeName = "VK_LAYER_LUNARG_vktrace";
- public static FixedUtf8String RenderdocCaptureLayerName = "VK_LAYER_RENDERDOC_Capture";
- public static FixedUtf8String main = "main";
- }
-
- public Instance () {
- init ();
- }
-
- unsafe bool ExtensionIsSupported (FixedUtf8String layer, string extName) {
- uint count;
- Utils.CheckResult (vkEnumerateInstanceExtensionProperties ((IntPtr)layer, out count, IntPtr.Zero));
- VkExtensionProperties[] tmp = new VkExtensionProperties[count];
- Utils.CheckResult (vkEnumerateInstanceExtensionProperties (layer, out count, tmp.Pin ()));
- tmp.Unpin ();
-
- fixed (VkExtensionProperties* ep = tmp) {
- for (int i = 0; i < tmp.Length; i++) {
- IntPtr n = (IntPtr)ep[i].extensionName;
- if (Marshal.PtrToStringAnsi (n) == extName)
- return true;
- }
- }
- return false;
- }
-
+ public static FixedUtf8String main = "main";
+ }
+ const string strValidationLayer = "VK_LAYER_KHRONOS_validation";
+ const string strRenderDocLayer = "VK_LAYER_RENDERDOC_Capture";
- void init () {
+ /// <summary>
+ /// Create a new vulkan instance with enabled extensions given as argument.
+ /// </summary>
+ /// <param name="extensions">List of extension to enable if supported</param>
+ public Instance (params string[] extensions) {
List<IntPtr> instanceExtensions = new List<IntPtr> ();
List<IntPtr> enabledLayerNames = new List<IntPtr> ();
- instanceExtensions.Add (Strings.VK_KHR_SURFACE_EXTENSION_NAME);
- if (RuntimeInformation.IsOSPlatform (OSPlatform.Windows)) {
- instanceExtensions.Add (Strings.VK_KHR_WIN32_SURFACE_EXTENSION_NAME);
- } else if (RuntimeInformation.IsOSPlatform (OSPlatform.Linux)) {
- instanceExtensions.Add (Strings.VK_KHR_XCB_SURFACE_EXTENSION_NAME);
- } else {
- throw new PlatformNotSupportedException ();
- }
-
- if (VALIDATION) {
- enabledLayerNames.Add (Strings.LayerValidation);
- //enabledLayerNames.Add (Strings.LayerValidation_old);
+ string[] supportedExts = SupportedExtensions (IntPtr.Zero);
- if (DEBUG_UTILS) {
- //if (ExtensionIsSupported(Strings.LayerValidation, Strings.VK_EXT_DEBUG_UTILS_EXTENSION_NAME))
- //instanceExtensions.Add (Strings.VK_EXT_DEBUG_UTILS_EXTENSION_NAME);
- instanceExtensions.Add (Strings.VK_EXT_DEBUG_REPORT_EXTENSION_NAME);
+ using (PinnedObjects pctx = new PinnedObjects ()) {
+ for (int i = 0; i < extensions.Length; i++) {
+ if (supportedExts.Contains (extensions[i]))
+ instanceExtensions.Add (extensions[i].Pin (pctx));
+ else
+ Console.WriteLine ($"Vulkan initialisation: Unsupported extension: {extensions[i]}");
}
- }
- if (RENDER_DOC_CAPTURE)
- enabledLayerNames.Add (Strings.RenderdocCaptureLayerName);
+ if (VALIDATION)
+ enabledLayerNames.Add (strValidationLayer.Pin (pctx));
+ if (RENDER_DOC_CAPTURE)
+ enabledLayerNames.Add (strRenderDocLayer.Pin (pctx));
- VkApplicationInfo appInfo = new VkApplicationInfo () {
- sType = VkStructureType.ApplicationInfo,
- apiVersion = new Vulkan.Version (1, 0, 0),
- pApplicationName = Strings.Name,
- pEngineName = Strings.Name,
- };
- VkInstanceCreateInfo instanceCreateInfo = VkInstanceCreateInfo.New ();
- instanceCreateInfo.pApplicationInfo = appInfo.Pin ();
+ VkApplicationInfo appInfo = new VkApplicationInfo () {
+ sType = VkStructureType.ApplicationInfo,
+ apiVersion = new Vulkan.Version (VK_MAJOR, VK_MINOR, 0),
+ pApplicationName = ENGINE_NAME.Pin (pctx),
+ pEngineName = APPLICATION_NAME.Pin (pctx),
+ };
- if (instanceExtensions.Count > 0) {
- instanceCreateInfo.enabledExtensionCount = (uint)instanceExtensions.Count;
- instanceCreateInfo.ppEnabledExtensionNames = instanceExtensions.Pin ();
- }
- if (enabledLayerNames.Count > 0) {
- instanceCreateInfo.enabledLayerCount = (uint)enabledLayerNames.Count;
- instanceCreateInfo.ppEnabledLayerNames = enabledLayerNames.Pin ();
+ VkInstanceCreateInfo instanceCreateInfo = VkInstanceCreateInfo.New ();
+ instanceCreateInfo.pApplicationInfo = appInfo.Pin (pctx);
+
+ if (instanceExtensions.Count > 0) {
+ instanceCreateInfo.enabledExtensionCount = (uint)instanceExtensions.Count;
+ instanceCreateInfo.ppEnabledExtensionNames = instanceExtensions.Pin (pctx);
+ }
+ if (enabledLayerNames.Count > 0) {
+ instanceCreateInfo.enabledLayerCount = (uint)enabledLayerNames.Count;
+ instanceCreateInfo.ppEnabledLayerNames = enabledLayerNames.Pin (pctx);
+ }
+
+ VkResult result = vkCreateInstance (ref instanceCreateInfo, IntPtr.Zero, out inst);
+ if (result != VkResult.Success)
+ throw new InvalidOperationException ("Could not create Vulkan instance. Error: " + result);
+
+ Vk.LoadInstanceFunctionPointers (inst);
}
+ }
- VkResult result = vkCreateInstance (ref instanceCreateInfo, IntPtr.Zero, out inst);
- if (result != VkResult.Success)
- throw new InvalidOperationException ("Could not create Vulkan instance. Error: " + result);
+ public string[] SupportedExtensions (IntPtr layer) {
+ Utils.CheckResult (vkEnumerateInstanceExtensionProperties (layer, out uint count, IntPtr.Zero));
- Vk.LoadInstanceFunctionPointers (inst);
+ int sizeStruct = Marshal.SizeOf<VkExtensionProperties> ();
+ IntPtr ptrSupExts = Marshal.AllocHGlobal (sizeStruct * (int)count);
+ Utils.CheckResult (vkEnumerateInstanceExtensionProperties (layer, out count, ptrSupExts));
- appInfo.Unpin ();
+ string[] result = new string[count];
+ IntPtr tmp = ptrSupExts;
+ for (int i = 0; i < count; i++) {
+ result[i] = Marshal.PtrToStringAnsi (tmp);
+ tmp += sizeStruct;
+ }
- if (instanceExtensions.Count > 0)
- instanceExtensions.Unpin ();
- if (enabledLayerNames.Count > 0)
- enabledLayerNames.Unpin ();
+ Marshal.FreeHGlobal (ptrSupExts);
+ return result;
}
public PhysicalDeviceCollection GetAvailablePhysicalDevice () => new PhysicalDeviceCollection (inst);
return surf;
}
public void GetDelegate<T> (string name, out T del) {
- using (FixedUtf8String n = new FixedUtf8String (name)) {
- del = Marshal.GetDelegateForFunctionPointer<T> (vkGetInstanceProcAddr (Handle, (IntPtr)n));
- }
- }
+ using (FixedUtf8String n = new FixedUtf8String (name)) {
+ del = Marshal.GetDelegateForFunctionPointer<T> (vkGetInstanceProcAddr (Handle, (IntPtr)n));
+ }
+ }
- #region IDisposable Support
- private bool disposedValue = false;
+ #region IDisposable Support
+ private bool disposedValue = false;
- protected virtual void Dispose (bool disposing) {
- if (!disposedValue) {
+ protected virtual void Dispose (bool disposing) {
+ if (!disposedValue) {
if (disposing) {
// TODO: supprimer l'état managé (objets managés).
} else
System.Diagnostics.Debug.WriteLine ("Instance disposed by Finalizer");
-
- vkDestroyInstance (inst, IntPtr.Zero);
-
- disposedValue = true;
- }
- }
-
- ~Instance () {
- Dispose(false);
- }
-
- public void Dispose () {
- Dispose (true);
- GC.SuppressFinalize(this);
- }
- #endregion
- }
+
+ vkDestroyInstance (inst, IntPtr.Zero);
+
+ disposedValue = true;
+ }
+ }
+
+ ~Instance () {
+ Dispose (false);
+ }
+
+ public void Dispose () {
+ Dispose (true);
+ GC.SuppressFinalize (this);
+ }
+ #endregion
+ }
}
-//
-// PhysicalDevice.cs
+// Copyright (c) 2019 Jean-Philippe Bruyère <jp_bruyere@hotmail.com>
//
-// Author:
-// Jean-Philippe Bruyère <jp_bruyere@hotmail.com>
-//
-// Copyright (c) 2019 jp
-//
-// Permission is hereby granted, free of charge, to any person obtaining a copy
-// of this software and associated documentation files (the "Software"), to deal
-// in the Software without restriction, including without limitation the rights
-// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
-// copies of the Software, and to permit persons to whom the Software is
-// furnished to do so, subject to the following conditions:
-//
-// The above copyright notice and this permission notice shall be included in
-// all copies or substantial portions of the Software.
-//
-// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
-// THE SOFTWARE.
+// This code is licensed under the MIT license (MIT) (http://opensource.org/licenses/MIT)
using System;
using Vulkan;
using static Vulkan.Vk;
using System.Collections;
using System.Collections.Generic;
using System.Runtime.InteropServices;
-
using System.Linq;
namespace vke {
- public class PhysicalDeviceCollection : IEnumerable<PhysicalDevice> {
- VkInstance inst;
- PhysicalDevice[] phys;
-
+ /// <summary>
+ /// Collection of physical devices returned by the vulkan instance.
+ /// </summary>
+ public class PhysicalDeviceCollection : IEnumerable<PhysicalDevice> {
+ readonly VkInstance inst;
+ readonly PhysicalDevice[] phys;
+
+ /// <summary>
+ /// Retrieve the physical devices available for the provided vulkan instance
+ /// </summary>
+ /// <param name="instance">The vulkan instance to retrieve the physical devices from.</param>
public PhysicalDeviceCollection (VkInstance instance) {
inst = instance;
- init ();
- }
+ CheckResult (vkEnumeratePhysicalDevices (inst, out uint gpuCount, IntPtr.Zero));
+ if (gpuCount <= 0)
+ throw new Exception ("No GPU found");
- public PhysicalDevice this[int i] {
- get {
- return phys[i];
- }
- }
-
- public IEnumerator<PhysicalDevice> GetEnumerator () {
- return ((IEnumerable<PhysicalDevice>)phys).GetEnumerator ();
- }
+ IntPtr gpus = Marshal.AllocHGlobal (Marshal.SizeOf<IntPtr> () * (int)gpuCount);
+ CheckResult (vkEnumeratePhysicalDevices (inst, out gpuCount, gpus), "Could not enumerate physical devices.");
- IEnumerator IEnumerable.GetEnumerator () {
- return ((IEnumerable<PhysicalDevice>)phys).GetEnumerator ();
- }
-
- void init () {
- uint gpuCount = 0;
- CheckResult (vkEnumeratePhysicalDevices (inst, out gpuCount, IntPtr.Zero));
- if (gpuCount <= 0)
- throw new Exception ("No GPU found");
-
- IntPtr gpus = Marshal.AllocHGlobal (Marshal.SizeOf<IntPtr> ()* (int)gpuCount);
- CheckResult (vkEnumeratePhysicalDevices (inst, out gpuCount, gpus), "Could not enumerate physical devices.");
-
- phys = new PhysicalDevice[gpuCount];
+ phys = new PhysicalDevice[gpuCount];
- for (int i = 0; i < gpuCount; i++)
- phys[i] = new PhysicalDevice (Marshal.ReadIntPtr(gpus + i * Marshal.SizeOf<IntPtr>()));
+ for (int i = 0; i < gpuCount; i++)
+ phys[i] = new PhysicalDevice (Marshal.ReadIntPtr (gpus + i * Marshal.SizeOf<IntPtr> ()));
Marshal.FreeHGlobal (gpus);
- }
+ }
+
+ public PhysicalDevice this[int i] => phys[i];
+ public IEnumerator<PhysicalDevice> GetEnumerator () => ((IEnumerable<PhysicalDevice>)phys).GetEnumerator ();
+ IEnumerator IEnumerable.GetEnumerator () => ((IEnumerable<PhysicalDevice>)phys).GetEnumerator ();
}
+ /// <summary>
+ /// Vke class that encapsulate a physical device.
+ /// </summary>
public class PhysicalDevice {
- IntPtr phy;
+ readonly IntPtr phy;
public VkPhysicalDeviceMemoryProperties memoryProperties { get; private set; }
public VkQueueFamilyProperties[] QueueFamilies { get; private set; }
public VkPhysicalDeviceProperties Properties {
get {
- VkPhysicalDeviceProperties pdp;
- vkGetPhysicalDeviceProperties (phy, out pdp);
+ vkGetPhysicalDeviceProperties (phy, out VkPhysicalDeviceProperties pdp);
return pdp;
}
}
public VkPhysicalDeviceFeatures Features {
get {
- VkPhysicalDeviceFeatures df;
- vkGetPhysicalDeviceFeatures (phy, out df);
+ vkGetPhysicalDeviceFeatures (phy, out VkPhysicalDeviceFeatures df);
return df;
}
}
public bool HasSwapChainSupport { get; private set; }
public IntPtr Handle => phy;
+ public bool GetDeviceExtensionSupported (string extName) => SupportedExtensions (IntPtr.Zero).Contains (extName);
- public PhysicalDevice (IntPtr vkPhy) {
+ #region CTOR
+ internal PhysicalDevice (IntPtr vkPhy) {
phy = vkPhy;
- init ();
- }
- unsafe void init () {
- // Gather physical Device memory properties
- IntPtr tmp = Marshal.AllocHGlobal (Marshal.SizeOf<VkPhysicalDeviceMemoryProperties>());
- vkGetPhysicalDeviceMemoryProperties (phy, tmp);
- memoryProperties = Marshal.PtrToStructure<VkPhysicalDeviceMemoryProperties> (tmp);
+ // Gather physical Device memory properties
+ IntPtr tmp = Marshal.AllocHGlobal (Marshal.SizeOf<VkPhysicalDeviceMemoryProperties> ());
+ vkGetPhysicalDeviceMemoryProperties (phy, tmp);
+ memoryProperties = Marshal.PtrToStructure<VkPhysicalDeviceMemoryProperties> (tmp);
- uint queueFamilyCount = 0;
- vkGetPhysicalDeviceQueueFamilyProperties (phy, out queueFamilyCount, IntPtr.Zero);
- QueueFamilies = new VkQueueFamilyProperties[queueFamilyCount];
+ vkGetPhysicalDeviceQueueFamilyProperties (phy, out uint queueFamilyCount, IntPtr.Zero);
+ QueueFamilies = new VkQueueFamilyProperties[queueFamilyCount];
- if (queueFamilyCount <= 0)
- throw new Exception ("No queues found for physical device");
+ if (queueFamilyCount <= 0)
+ throw new Exception ("No queues found for physical device");
vkGetPhysicalDeviceQueueFamilyProperties (phy, out queueFamilyCount, QueueFamilies.Pin ());
QueueFamilies.Unpin ();
- uint propCount = 0;
-
- vkEnumerateDeviceExtensionProperties (phy, IntPtr.Zero, out propCount, IntPtr.Zero);
-
- VkExtensionProperties[] extProps = new VkExtensionProperties[propCount];
-
- vkEnumerateDeviceExtensionProperties (phy, IntPtr.Zero, out propCount, extProps.Pin ());
- extProps.Unpin ();
-
- for (int i = 0; i < extProps.Length; i++)
- {
- fixed (VkExtensionProperties* ep = extProps) {
- IntPtr n = (IntPtr)ep[i].extensionName;
- switch (Marshal.PtrToStringAnsi(n))
- {
- case "VK_KHR_swapchain":
- HasSwapChainSupport = true;
- break;
- }
- }
- }
- }
-
- public unsafe bool GetDeviceExtensionSupported (string extName) {
- uint propCount = 0;
-
- vkEnumerateDeviceExtensionProperties (phy, IntPtr.Zero, out propCount, IntPtr.Zero);
+ HasSwapChainSupport = GetDeviceExtensionSupported (Ext.D.VK_KHR_swapchain);
+ }
+ #endregion
- VkExtensionProperties[] extProps = new VkExtensionProperties[propCount];
+ public string[] SupportedExtensions (IntPtr layer) {
+ CheckResult (vkEnumerateDeviceExtensionProperties (phy, layer, out uint count, IntPtr.Zero));
- vkEnumerateDeviceExtensionProperties (phy, IntPtr.Zero, out propCount, extProps.Pin ());
- extProps.Unpin ();
+ int sizeStruct = Marshal.SizeOf<VkExtensionProperties> ();
+ IntPtr ptrSupExts = Marshal.AllocHGlobal (sizeStruct * (int)count);
+ CheckResult (vkEnumerateDeviceExtensionProperties (phy, layer, out count, ptrSupExts));
- for (int i = 0; i < extProps.Length; i++) {
- fixed (VkExtensionProperties* ep = extProps) {
- IntPtr n = (IntPtr)ep[i].extensionName;
- if (Marshal.PtrToStringAnsi (n) == extName)
- return true;
- }
+ string[] result = new string[count];
+ IntPtr tmp = ptrSupExts;
+ for (int i = 0; i < count; i++) {
+ result[i] = Marshal.PtrToStringAnsi (tmp);
+ tmp += sizeStruct;
}
- Console.WriteLine ($"INFO: unsuported device extension: {extName}");
- return false;
- }
+ Marshal.FreeHGlobal (ptrSupExts);
+ return result;
+ }
- public bool GetPresentIsSupported (uint qFamilyIndex, VkSurfaceKHR surf) {
- VkBool32 isSupported = false;
- vkGetPhysicalDeviceSurfaceSupportKHR (phy, qFamilyIndex, surf, out isSupported);
+ public bool GetPresentIsSupported (uint qFamilyIndex, VkSurfaceKHR surf) {
+ vkGetPhysicalDeviceSurfaceSupportKHR (phy, qFamilyIndex, surf, out VkBool32 isSupported);
return isSupported;
}
- public VkSurfaceCapabilitiesKHR GetSurfaceCapabilities (VkSurfaceKHR surf) {
- VkSurfaceCapabilitiesKHR caps;
- vkGetPhysicalDeviceSurfaceCapabilitiesKHR (phy, surf, out caps);
+ public VkSurfaceCapabilitiesKHR GetSurfaceCapabilities (VkSurfaceKHR surf) {
+ vkGetPhysicalDeviceSurfaceCapabilitiesKHR (phy, surf, out VkSurfaceCapabilitiesKHR caps);
return caps;
}
- unsafe public VkSurfaceFormatKHR[] GetSurfaceFormats (VkSurfaceKHR surf) {
- uint count = 0;
- vkGetPhysicalDeviceSurfaceFormatsKHR (phy, surf, out count, IntPtr.Zero);
+ public VkSurfaceFormatKHR[] GetSurfaceFormats (VkSurfaceKHR surf) {
+ vkGetPhysicalDeviceSurfaceFormatsKHR (phy, surf, out uint count, IntPtr.Zero);
VkSurfaceFormatKHR[] formats = new VkSurfaceFormatKHR[count];
vkGetPhysicalDeviceSurfaceFormatsKHR (phy, surf, out count, formats.Pin());
return formats;
}
- unsafe public VkPresentModeKHR[] GetSurfacePresentModes (VkSurfaceKHR surf) {
- uint count = 0;
- vkGetPhysicalDeviceSurfacePresentModesKHR (phy, surf, out count, IntPtr.Zero);
+ public VkPresentModeKHR[] GetSurfacePresentModes (VkSurfaceKHR surf) {
+ vkGetPhysicalDeviceSurfacePresentModesKHR (phy, surf, out uint count, IntPtr.Zero);
VkPresentModeKHR[] modes = new VkPresentModeKHR[count];
vkGetPhysicalDeviceSurfacePresentModesKHR (phy, surf, out count, modes.Pin());
return modes;
}
- public VkFormatProperties GetFormatProperties (VkFormat format) {
- VkFormatProperties properties;
- vkGetPhysicalDeviceFormatProperties (phy, format, out properties);
+ public VkFormatProperties GetFormatProperties (VkFormat format) {
+ vkGetPhysicalDeviceFormatProperties (phy, format, out VkFormatProperties properties);
return properties;
}
}
-//
-// Queue.cs
+// Copyright (c) 2019 Jean-Philippe Bruyère <jp_bruyere@hotmail.com>
//
-// Author:
-// Jean-Philippe Bruyère <jp_bruyere@hotmail.com>
-//
-// Copyright (c) 2019 jp
-//
-// Permission is hereby granted, free of charge, to any person obtaining a copy
-// of this software and associated documentation files (the "Software"), to deal
-// in the Software without restriction, including without limitation the rights
-// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
-// copies of the Software, and to permit persons to whom the Software is
-// furnished to do so, subject to the following conditions:
-//
-// The above copyright notice and this permission notice shall be included in
-// all copies or substantial portions of the Software.
-//
-// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
-// THE SOFTWARE.
+// This code is licensed under the MIT license (MIT) (http://opensource.org/licenses/MIT)
using System;
-using System.Collections;
using Vulkan;
using static Vulkan.Vk;
/// <returns>
/// The character representation of the codepoint.
/// </returns>
- public char ToChar() => Encoding.UTF32.GetChars (new byte[] { byte0, byte0, byte0, byte0 })[0];
+ public char ToChar() => Encoding.UTF32.GetChars (new byte[] { byte0, byte1, byte2, byte3 })[0];
/// <summary>
/// Converts the value of this instance to its equivalent string representation.
/// </summary>
{
IntPtr names = GetRequiredInstanceExtensions(out int count);
- var result = new string[count];
+ string[] result = new string[count];
for (int nameIndex = 0; nameIndex < count; nameIndex++)
{
- IntPtr name = Marshal.ReadIntPtr (names, nameIndex);
+ IntPtr name = Marshal.ReadIntPtr (names, nameIndex * Marshal.SizeOf<IntPtr>());
result[nameIndex] = Marshal.PtrToStringAnsi(name);
}
//
// This code is licensed under the MIT license (MIT) (http://opensource.org/licenses/MIT)
using System;
+using System.Collections.Generic;
using System.IO;
-
-using Vulkan;
-using vke;
using System.Runtime.InteropServices;
-using System.Collections.Generic;
+using vke;
+using Vulkan;
namespace KTX {
<EnableDefaultNoneItems>false</EnableDefaultNoneItems>
<LangVersion>7.2</LangVersion>
+ <GenerateDocumentationFile>true</GenerateDocumentationFile>
+ <NoWarn>$(NoWarn);1591</NoWarn>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
<ItemGroup>
<PackageReference Include="SpirVTasks" Version="0.1.10-beta" />
- <PackageReference Include="Vulkan" Version="0.1.6-beta" />
+ <PackageReference Include="Vulkan" Version="0.1.7" />
</ItemGroup>
<ItemGroup>
<GLSLShader Include="shaders\**\*.frag;shaders\**\*.vert;shaders\**\*.comp;shaders\**\*.geom">