aboutsummaryrefslogtreecommitdiffstatsci
path: root/vke/src
diff options
context:
space:
mode:
authorJean-Philippe Bruyère <jp_bruyere@hotmail.com>2019-04-05 14:13:20 +0200
committerJean-Philippe Bruyère <jp_bruyere@hotmail.com>2019-04-05 14:13:20 +0200
commit04d94de392b6e5ca4f82acc233df7b3f97abca36 (patch)
tree27df9645ea97cf36c99cb4f8ed5f347cc00cb458 /vke/src
parent7d305b07ccaeb2a8cd342e3395db46f2f8fffade (diff)
Activable pattern wip
Diffstat (limited to 'vke/src')
-rw-r--r--vke/src/Activable.cs71
-rw-r--r--vke/src/Buffer.cs26
-rw-r--r--vke/src/DescriptorSetLayout.cs51
-rw-r--r--vke/src/Device.cs32
-rw-r--r--vke/src/ExtensionMethods.cs17
-rw-r--r--vke/src/FrameBuffer.cs122
-rw-r--r--vke/src/Image.cs37
-rw-r--r--vke/src/Pipeline.cs187
-rw-r--r--vke/src/PipelineConfig.cs163
-rw-r--r--vke/src/PipelineLayout.cs74
-rw-r--r--vke/src/RenderPass.cs176
-rw-r--r--vke/src/Resource.cs52
-rw-r--r--vke/src/ShaderInfo.cs69
13 files changed, 620 insertions, 457 deletions
diff --git a/vke/src/Activable.cs b/vke/src/Activable.cs
new file mode 100644
index 0000000..da5fdfd
--- /dev/null
+++ b/vke/src/Activable.cs
@@ -0,0 +1,71 @@
+//
+// Activable.cs
+//
+// 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.
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using Vulkan;
+using static Vulkan.VulkanNative;
+
+namespace VKE {
+ public enum ActivableState { Init, Activated, Disposed };
+ public abstract class Activable : IDisposable {
+ protected uint references;
+ protected ActivableState state;
+
+ public Device dev { get; private set; }
+
+ protected Activable (Device dev) {
+ this.dev = dev;
+ }
+
+ public virtual void Activate () {
+ if (state == ActivableState.Disposed)
+ GC.ReRegisterForFinalize (this);
+ state = ActivableState.Activated;
+ references++;
+ }
+
+ public void Desactivate () {
+ }
+ #region IDisposable Support
+ protected virtual void Dispose (bool disposing) {
+ state = ActivableState.Disposed;
+ }
+
+ ~Activable() {
+ Dispose(false);
+ }
+ public void Dispose () {
+ if (references>0)
+ references--;
+ if (references>0)
+ return;
+ Dispose (true);
+ GC.SuppressFinalize(this);
+ }
+ #endregion
+ }
+}
diff --git a/vke/src/Buffer.cs b/vke/src/Buffer.cs
index 1ad293e..d11c7da 100644
--- a/vke/src/Buffer.cs
+++ b/vke/src/Buffer.cs
@@ -111,9 +111,12 @@ namespace VKE {
}
public override void Activate () {
- allocateMemory ();
- bindMemory (0);
- SetupDescriptor ();
+ if (state != ActivableState.Activated) {
+ allocateMemory ();
+ bindMemory (0);
+ SetupDescriptor ();
+ }
+ base.Activate ();
}
@@ -158,18 +161,11 @@ namespace VKE {
Utils.CheckResult (vkBindBufferMemory (dev.VkDev, handle, vkMemory, offset));
}
protected override void Dispose (bool disposing) {
- if (references>0)
- return;
- if (!isDisposed) {
- base.Dispose (disposing);
- if (!disposing)
- System.Diagnostics.Debug.WriteLine ($"A Buffer Ressource was not properly disposed.");
-
-
- vkDestroyBuffer (dev.VkDev, handle, IntPtr.Zero);
-
- isDisposed = true;
- }
+ if (state == ActivableState.Activated) {
+ base.Dispose (disposing);
+ vkDestroyBuffer (dev.VkDev, handle, IntPtr.Zero);
+ }
+ state = ActivableState.Disposed;
}
}
}
diff --git a/vke/src/DescriptorSetLayout.cs b/vke/src/DescriptorSetLayout.cs
index 4d58ad3..49f5403 100644
--- a/vke/src/DescriptorSetLayout.cs
+++ b/vke/src/DescriptorSetLayout.cs
@@ -24,19 +24,19 @@
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
using System;
+using System.Collections.Generic;
using Vulkan;
using static Vulkan.VulkanNative;
namespace VKE {
- public class DescriptorSetLayout : IDisposable {
+ public sealed class DescriptorSetLayout : Activable {
internal VkDescriptorSetLayout handle;
- internal Device dev;
+
public VkDescriptorSetLayoutCreateFlags Flags { get; private set; } = VkDescriptorSetLayoutCreateFlags.None;
+ public List<VkDescriptorSetLayoutBinding> Bindings { get; private set; } = new List<VkDescriptorSetLayoutBinding> ();
- public NativeList<VkDescriptorSetLayoutBinding> Bindings = new NativeList<VkDescriptorSetLayoutBinding> ();
-
- public DescriptorSetLayout (Device device, VkDescriptorSetLayoutCreateFlags flags) {
- dev = device;
+ #region CTORS
+ public DescriptorSetLayout (Device device, VkDescriptorSetLayoutCreateFlags flags) : base (device) {
Flags = flags;
}
public DescriptorSetLayout (Device device, params VkDescriptorSetLayoutBinding[] bindings)
@@ -48,35 +48,24 @@ namespace VKE {
Bindings.Add (b);
Activate ();
}
- public void Activate () {
- if (isDisposed) {
- GC.ReRegisterForFinalize (this);
- isDisposed = false;
- }
- VkDescriptorSetLayoutCreateInfo info = new VkDescriptorSetLayoutCreateInfo (Flags, Bindings.Count, Bindings.Data);
- Utils.CheckResult (vkCreateDescriptorSetLayout (dev.VkDev, ref info, IntPtr.Zero, out handle));
- }
-
- #region IDisposable Support
- private bool isDisposed = false; // Pour détecter les appels redondants
+ #endregion
- protected virtual void Dispose (bool disposing) {
- if (!isDisposed) {
- if (disposing) {
- Bindings.Dispose ();
- } else
- System.Diagnostics.Debug.WriteLine ("A descriptorSetLayout has not been disposed.");
- vkDestroyDescriptorSetLayout (dev.VkDev, handle, IntPtr.Zero);
- isDisposed = true;
+ public override void Activate () {
+ if (state != ActivableState.Activated) {
+ VkDescriptorSetLayoutCreateInfo info = new VkDescriptorSetLayoutCreateInfo (Flags, (uint)Bindings.Count, Bindings.Pin());
+ Utils.CheckResult (vkCreateDescriptorSetLayout (dev.VkDev, ref info, IntPtr.Zero, out handle));
+ Bindings.Unpin ();
}
+ base.Activate ();
}
- ~DescriptorSetLayout() {
- Dispose(false);
- }
- public void Dispose () {
- Dispose (true);
- GC.SuppressFinalize(this);
+ #region IDisposable Support
+ protected override void Dispose (bool disposing) {
+ if (!disposing)
+ System.Diagnostics.Debug.WriteLine ("VKE DescriptorSetLayout disposed by finalizer");
+ if (state == ActivableState.Activated)
+ vkDestroyDescriptorSetLayout (dev.VkDev, handle, IntPtr.Zero);
+ base.Dispose (disposing);
}
#endregion
}
diff --git a/vke/src/Device.cs b/vke/src/Device.cs
index 85b2f48..869f639 100644
--- a/vke/src/Device.cs
+++ b/vke/src/Device.cs
@@ -45,13 +45,13 @@ namespace VKE {
unsafe public void Activate (VkPhysicalDeviceFeatures enabledFeatures, params string[] extensions) {
- NativeList<VkDeviceQueueCreateInfo> qInfos = new NativeList<VkDeviceQueueCreateInfo> ();
- NativeList<float> priorities = null;
+ List<VkDeviceQueueCreateInfo> qInfos = new List<VkDeviceQueueCreateInfo> ();
+ List<List<float>> prioritiesLists = new List<List<float>> ();
foreach (IGrouping<uint, Queue> qfams in queues.GroupBy (q => q.qFamIndex)) {
int qTot = qfams.Count ();
uint qIndex = 0;
- priorities = new NativeList<float> ();
+ List<float>priorities = new List<float> ();
bool qCountReached = false;//true when queue count of that family is reached
foreach (Queue q in qfams) {
@@ -62,18 +62,18 @@ namespace VKE {
qIndex = 0;
qCountReached = true;
}
- }
+ }
qInfos.Add (new VkDeviceQueueCreateInfo {
sType = VkStructureType.DeviceQueueCreateInfo,
queueCount = qCountReached ? phy.QueueFamilies[qfams.Key].queueCount : qIndex,
queueFamilyIndex = qfams.Key,
- pQueuePriorities = (float*)priorities.Data.ToPointer ()
+ pQueuePriorities = priorities.Pin ()
});
- }
- float tmp = priorities[0];
+ prioritiesLists.Add (priorities);//add for unpined
+ }
- NativeList<IntPtr> deviceExtensions = new NativeList<IntPtr> ();
+ List<IntPtr> deviceExtensions = new List<IntPtr> ();
for (int i = 0; i < extensions.Length; i++) {
deviceExtensions.Add (new FixedUtf8String(extensions[i]));
}
@@ -81,20 +81,22 @@ namespace VKE {
VkPhysicalDeviceFeatures features = enabledFeatures;
VkDeviceCreateInfo deviceCreateInfo = VkDeviceCreateInfo.New ();
- deviceCreateInfo.queueCreateInfoCount = qInfos.Count;
- deviceCreateInfo.pQueueCreateInfos = (VkDeviceQueueCreateInfo*)qInfos.Data.ToPointer();
+ deviceCreateInfo.queueCreateInfoCount = (uint)qInfos.Count;
+ deviceCreateInfo.pQueueCreateInfos = qInfos.Pin();
deviceCreateInfo.pEnabledFeatures = &features;
if (deviceExtensions.Count > 0) {
- deviceCreateInfo.enabledExtensionCount = deviceExtensions.Count;
- deviceCreateInfo.ppEnabledExtensionNames = deviceExtensions.Data;
+ deviceCreateInfo.enabledExtensionCount = (uint)deviceExtensions.Count;
+ deviceCreateInfo.ppEnabledExtensionNames = deviceExtensions.Pin();
}
Utils.CheckResult (vkCreateDevice (phy.Handle, ref deviceCreateInfo, IntPtr.Zero, out dev));
- qInfos.Dispose ();
- priorities.Dispose ();
- deviceExtensions.Dispose ();
+ qInfos.Unpin ();
+ foreach (List<float> fa in prioritiesLists)
+ fa.Unpin ();
+
+ deviceExtensions.Unpin ();
foreach (Queue q in queues)
q.updateHandle ();
diff --git a/vke/src/ExtensionMethods.cs b/vke/src/ExtensionMethods.cs
index 1cf01cd..620c379 100644
--- a/vke/src/ExtensionMethods.cs
+++ b/vke/src/ExtensionMethods.cs
@@ -62,6 +62,21 @@ namespace VKE {
handles[obj].Free ();
handles.Remove (obj);
}
-
+ public static IntPtr Pin<T> (this List<T> obj) {
+ if (handles.ContainsKey (obj))
+ Debug.WriteLine ("Pinning already pinned object: {0}", obj);
+
+ GCHandle hnd = GCHandle.Alloc (obj.ToArray(), GCHandleType.Pinned);
+ handles.Add (obj, hnd);
+ return hnd.AddrOfPinnedObject ();
+ }
+ //public static void Unpin<T> (this List<T> obj) {
+ // if (!handles.ContainsKey (obj)) {
+ // Debug.WriteLine ("Trying to unpin {0}, but object has not been pinned.", obj);
+ // return;
+ // }
+ // handles[obj].Free ();
+ // handles.Remove (obj);
+ //}
}
}
diff --git a/vke/src/FrameBuffer.cs b/vke/src/FrameBuffer.cs
index 431c21e..e0b81a7 100644
--- a/vke/src/FrameBuffer.cs
+++ b/vke/src/FrameBuffer.cs
@@ -32,17 +32,19 @@ using static Vulkan.VulkanNative;
namespace VKE {
- public class Framebuffer : IDisposable {
+ public class Framebuffer : Activable {
internal VkFramebuffer handle;
RenderPass renderPass;
- public List<Image> attachments = new List<Image> ();
+
+ public List<Image> attachments = new List<Image> ();
VkFramebufferCreateInfo createInfo = VkFramebufferCreateInfo.New ();
+
public uint Width => createInfo.width;
public uint Height => createInfo.height;
public uint Layers => createInfo.layers;
- public Framebuffer (RenderPass _renderPass, uint _width, uint _height, uint _layers = 1) {
+ public Framebuffer (RenderPass _renderPass, uint _width, uint _height, uint _layers = 1) : base(_renderPass.dev) {
renderPass = _renderPass;
createInfo.width = _width;
createInfo.height = _height;
@@ -50,6 +52,46 @@ namespace VKE {
createInfo.renderPass = renderPass.handle;
}
+ public Framebuffer (RenderPass _renderPass, uint _width, uint _height, params Image[] views)
+ : this (_renderPass, _width, _height) {
+ for (int i = 0; i < views.Length; i++) {
+ Image v = views[i];
+ if (v == null) {
+ //automatically create attachment if not in unused state in the renderpass
+ VkAttachmentDescription ad = renderPass.attachments[i];
+ VkImageUsageFlags usage = VkImageUsageFlags.None;
+ VkImageAspectFlags aspectFlags = VkImageAspectFlags.None;
+
+ checkLayoutRequirements (ad.initialLayout, ref usage, ref aspectFlags);
+ checkLayoutRequirements (ad.finalLayout, ref usage, ref aspectFlags);
+ foreach (SubPass sp in renderPass.subpasses) {
+ //TODO:check subpass usage
+ }
+
+ v = new Image (renderPass.dev, ad.format, usage, VkMemoryPropertyFlags.DeviceLocal,
+ _width, _height, VkImageType.Image2D, ad.samples, VkImageTiling.Optimal, 1, createInfo.layers);
+ v.CreateView (VkImageViewType.Image2D, aspectFlags);
+ } else
+ v.Activate ();//increase ref and create handle if not already activated
+
+ attachments.Add (v);
+ }
+ Activate ();
+ }
+
+ public override void Activate () {
+ if (state != ActivableState.Activated) {
+ VkImageView[] views = attachments.Select (a => a.Descriptor.imageView).ToArray ();
+ createInfo.attachmentCount = (uint)views.Length;
+ createInfo.pAttachments = views.Pin ();
+
+ Utils.CheckResult (vkCreateFramebuffer (renderPass.dev.VkDev, ref createInfo, IntPtr.Zero, out handle));
+
+ views.Unpin ();
+ }
+ base.Activate ();
+ }
+
void checkLayoutRequirements (VkImageLayout layout, ref VkImageUsageFlags usage, ref VkImageAspectFlags aspectFlags) {
switch (layout) {
case VkImageLayout.ColorAttachmentOptimal:
@@ -84,71 +126,17 @@ namespace VKE {
}
}
-
- public Framebuffer (RenderPass _renderPass, uint _width, uint _height, params Image[] views)
- : this (_renderPass, _width, _height) {
- for (int i = 0; i < views.Length; i++) {
- Image v = views[i];
- if (v == null){
- //automatically create attachment if not in unused state in the renderpass
- VkAttachmentDescription ad = renderPass.attachments[i];
- VkImageUsageFlags usage = VkImageUsageFlags.None;
- VkImageAspectFlags aspectFlags = VkImageAspectFlags.None;
-
- checkLayoutRequirements (ad.initialLayout, ref usage, ref aspectFlags);
- checkLayoutRequirements (ad.finalLayout, ref usage, ref aspectFlags);
- foreach (SubPass sp in renderPass.subpasses) {
- //TODO:check subpass usage
- }
-
- v = new Image (renderPass.dev, ad.format, usage, VkMemoryPropertyFlags.DeviceLocal,
- _width, _height, VkImageType.Image2D, ad.samples, VkImageTiling.Optimal, 1, createInfo.layers);
- v.CreateView (VkImageViewType.Image2D, aspectFlags);
- }
- v.references++;
- attachments.Add (v);
- }
- Activate ();
- }
-
- public void Activate () {
- if (isDisposed) {
- GC.ReRegisterForFinalize (this);
- isDisposed = false;
- }
- VkImageView[] views;
- views = attachments.Select(a=>a.Descriptor.imageView).ToArray();
-
- createInfo.attachmentCount = (uint)views.Length;
- createInfo.pAttachments = views.Pin();
-
- Utils.CheckResult (vkCreateFramebuffer (renderPass.dev.VkDev, ref createInfo, IntPtr.Zero, out handle));
-
- views.Unpin();
- }
-
#region IDisposable Support
- private bool isDisposed = false; // Pour détecter les appels redondants
-
- protected virtual void Dispose (bool disposing) {
- if (!isDisposed) {
- renderPass.dev.DestroyFramebuffer (handle);
- if (disposing) {
- foreach (Image img in attachments)
- img.Dispose();
- } else
- System.Diagnostics.Debug.WriteLine ("A FrameBuffer has not been disposed.");
-
- isDisposed = true;
- }
- }
-
- ~Framebuffer () {
- Dispose (false);
- }
- public void Dispose () {
- Dispose (true);
- GC.SuppressFinalize (this);
+ protected override void Dispose (bool disposing) {
+ if (state == ActivableState.Activated)
+ dev.DestroyFramebuffer (handle);
+ if (disposing) {
+ foreach (Image img in attachments)
+ img.Dispose();
+ }else
+ System.Diagnostics.Debug.WriteLine ("VKE Activable object disposed by finalizer");
+
+ base.Dispose (disposing);
}
#endregion
diff --git a/vke/src/Image.cs b/vke/src/Image.cs
index a193544..295cdf1 100644
--- a/vke/src/Image.cs
+++ b/vke/src/Image.cs
@@ -46,8 +46,6 @@ namespace VKE {
/// </summary>
public Image (Device device, VkImage vkHandle, VkFormat format, VkImageUsageFlags usage, uint width, uint height)
: base (device, VkMemoryPropertyFlags.DeviceLocal) {
- dev = device;
-
info.imageType = VkImageType.Image2D;
info.format = format;
info.extent.width = width;
@@ -61,6 +59,8 @@ namespace VKE {
handle = vkHandle;
imported = true;
+
+ state = ActivableState.Activated;
references++;//increment ref because it is bound to swapchain
}
@@ -224,9 +224,11 @@ namespace VKE {
Utils.CheckResult (vkBindImageMemory (dev.VkDev, handle, vkMemory, offset));
}
public override void Activate () {
- Utils.CheckResult (vkCreateImage (dev.VkDev, ref info, IntPtr.Zero, out handle));
- allocateMemory ();
- bindMemory ();
+ if (state != ActivableState.Activated) {
+ Utils.CheckResult (vkCreateImage (dev.VkDev, ref info, IntPtr.Zero, out handle));
+ allocateMemory ();
+ bindMemory ();
+ }
base.Activate ();
}
@@ -457,26 +459,17 @@ namespace VKE {
}
protected override void Dispose (bool disposing) {
- if (references>0)
- return;
- if (!isDisposed) {
- if (!disposing)
- System.Diagnostics.Debug.WriteLine ($"An Image Ressource was not properly disposed.");
-
- if (Descriptor.sampler.Handle != 0)
+ if (state == ActivableState.Activated) {
+ if (Descriptor.sampler.Handle != 0)
dev.DestroySampler (Descriptor.sampler);
if (Descriptor.imageView.Handle != 0)
dev.DestroyImageView (Descriptor.imageView);
- if (imported)
- return;
-
- if (!imported)
- base.Dispose (disposing);
-
- dev.DestroyImage (handle);
-
- isDisposed = true;
- }
+ if (!imported) {
+ base.Dispose (disposing);
+ dev.DestroyImage (handle);
+ }
+ }
+ state = ActivableState.Disposed;
}
}
}
diff --git a/vke/src/Pipeline.cs b/vke/src/Pipeline.cs
index 3187e50..c3cb68d 100644
--- a/vke/src/Pipeline.cs
+++ b/vke/src/Pipeline.cs
@@ -30,37 +30,8 @@ using Vulkan;
using static Vulkan.VulkanNative;
namespace VKE {
- public class ShaderInfo : IDisposable {
- public VkShaderStageFlags StageFlags;
- public string SpirvPath;
- public FixedUtf8String EntryPoint;
-
- public ShaderInfo (VkShaderStageFlags _stageFlags, string _spirvPath, string _entryPoint = "main") {
- StageFlags = _stageFlags;
- SpirvPath = _spirvPath;
- EntryPoint = new FixedUtf8String (_entryPoint);
- }
-
- #region IDisposable Support
- private bool disposedValue = false; // Pour détecter les appels redondants
-
- protected virtual void Dispose (bool disposing) {
- if (!disposedValue) {
- if (disposing)
- EntryPoint.Dispose ();
-
- disposedValue = true;
- }
- }
- public void Dispose () {
- Dispose (true);
- }
- #endregion
- }
-
- public class Pipeline : IDisposable {
- internal VkPipeline handle;
- Device dev;
+ public class Pipeline : Activable {
+ internal VkPipeline handle;
VkPipelineBindPoint bindPoint = VkPipelineBindPoint.Graphics;
VkPipelineInputAssemblyStateCreateInfo inputAssemblyState = VkPipelineInputAssemblyStateCreateInfo.New ();
@@ -69,10 +40,10 @@ namespace VKE {
public VkPipelineDepthStencilStateCreateInfo depthStencilState = VkPipelineDepthStencilStateCreateInfo.New ();
public VkPipelineMultisampleStateCreateInfo multisampleState = VkPipelineMultisampleStateCreateInfo.New ();
- NativeList<VkPipelineColorBlendAttachmentState> blendAttachments = new NativeList<VkPipelineColorBlendAttachmentState>();
- NativeList<VkDynamicState> dynamicStates = new NativeList<VkDynamicState> ();
- public NativeList<VkVertexInputBindingDescription> vertexBindings = new NativeList<VkVertexInputBindingDescription> ();
- public NativeList<VkVertexInputAttributeDescription> vertexAttributes = new NativeList<VkVertexInputAttributeDescription> ();
+ List<VkPipelineColorBlendAttachmentState> blendAttachments = new List<VkPipelineColorBlendAttachmentState>();
+ List<VkDynamicState> dynamicStates = new List<VkDynamicState> ();
+ public List<VkVertexInputBindingDescription> vertexBindings = new List<VkVertexInputBindingDescription> ();
+ public List<VkVertexInputAttributeDescription> vertexAttributes = new List<VkVertexInputAttributeDescription> ();
public List<ShaderInfo> shaders = new List<ShaderInfo>();
public PipelineLayout Layout;
@@ -102,16 +73,16 @@ namespace VKE {
public void AddShader (VkShaderStageFlags _stageFlags, string _spirvPath, string _entryPoint = "main") {
shaders.Add (new ShaderInfo (_stageFlags, _spirvPath, _entryPoint));
}
+
+ #region CTORS
/// <summary>
/// Create a new Pipeline with supplied RenderPass
/// </summary>
public Pipeline (Device dev, RenderPass renderPass, VkPrimitiveTopology topology = VkPrimitiveTopology.TriangleList,
- VkSampleCountFlags samples = VkSampleCountFlags.Count1)
- {
- this.dev = dev;
+ VkSampleCountFlags samples = VkSampleCountFlags.Count1) : base (dev)
+ {
RenderPass = renderPass;
- RenderPass.references++;
inputAssemblyState.topology = topology;
@@ -126,10 +97,7 @@ namespace VKE {
viewportState.viewportCount = 1;
viewportState.scissorCount = 1;
- blendAttachments.Add (new VkPipelineColorBlendAttachmentState {
- colorWriteMask = VkColorComponentFlags.R | VkColorComponentFlags.G | VkColorComponentFlags.B | VkColorComponentFlags.A,
- blendEnable = False
- });
+ blendAttachments.Add (new VkPipelineColorBlendAttachmentState (false));
dynamicStates.Add (VkDynamicState.Viewport);
dynamicStates.Add (VkDynamicState.Scissor);
@@ -156,97 +124,82 @@ namespace VKE {
: this (dev, new RenderPass (dev, colorFormat, depthFormat, samples), topology,samples)
{
}
+ #endregion
- public unsafe void Activate () {
- if (isDisposed) {
- GC.ReRegisterForFinalize (this);
- isDisposed = false;
- }
-
- Layout.Activate ();
-
- VkGraphicsPipelineCreateInfo info = VkGraphicsPipelineCreateInfo.New ();
- info.renderPass = RenderPass.handle;
- info.layout = Layout.handle;
+ public override void Activate () {
+ if (state != ActivableState.Activated) {
+ Layout.Activate ();
+ RenderPass.Activate ();
- NativeList<VkPipelineShaderStageCreateInfo> shaderStages = new NativeList<VkPipelineShaderStageCreateInfo> ();
- foreach (ShaderInfo shader in shaders) {
- shaderStages.Add (new VkPipelineShaderStageCreateInfo {
- sType = VkStructureType.PipelineShaderStageCreateInfo,
- stage = shader.StageFlags,
- pName = shader.EntryPoint.StringPtr,
- module = dev.LoadSPIRVShader (shader.SpirvPath),
- });
- }
+ List<VkPipelineShaderStageCreateInfo> shaderStages = new List<VkPipelineShaderStageCreateInfo> ();
+ foreach (ShaderInfo shader in shaders)
+ shaderStages.Add (shader.GetStageCreateInfo(dev));
- VkPipelineColorBlendStateCreateInfo colorBlendInfo = VkPipelineColorBlendStateCreateInfo.New ();
- colorBlendInfo.attachmentCount = blendAttachments.Count;
- colorBlendInfo.pAttachments = (VkPipelineColorBlendAttachmentState*) blendAttachments.Data.ToPointer ();
+ VkPipelineColorBlendStateCreateInfo colorBlendInfo = VkPipelineColorBlendStateCreateInfo.New ();
+ colorBlendInfo.attachmentCount = (uint)blendAttachments.Count;
+ colorBlendInfo.pAttachments = blendAttachments.Pin ();
- VkPipelineDynamicStateCreateInfo dynStatesInfo = VkPipelineDynamicStateCreateInfo.New ();
- dynStatesInfo.dynamicStateCount = dynamicStates.Count;
- dynStatesInfo.pDynamicStates = (VkDynamicState*)dynamicStates.Data.ToPointer ();
+ VkPipelineDynamicStateCreateInfo dynStatesInfo = VkPipelineDynamicStateCreateInfo.New ();
+ dynStatesInfo.dynamicStateCount = (uint)dynamicStates.Count;
+ dynStatesInfo.pDynamicStates = dynamicStates.Pin ();
- VkPipelineVertexInputStateCreateInfo vertInputInfo = VkPipelineVertexInputStateCreateInfo.New ();
- vertInputInfo.vertexBindingDescriptionCount = vertexBindings.Count;
- vertInputInfo.pVertexBindingDescriptions = (VkVertexInputBindingDescription*)vertexBindings.Data.ToPointer ();
- vertInputInfo.vertexAttributeDescriptionCount = vertexAttributes.Count;
- vertInputInfo.pVertexAttributeDescriptions = (VkVertexInputAttributeDescription*)vertexAttributes.Data.ToPointer ();
+ VkPipelineVertexInputStateCreateInfo vertInputInfo = VkPipelineVertexInputStateCreateInfo.New ();
+ vertInputInfo.vertexBindingDescriptionCount = (uint)vertexBindings.Count;
+ vertInputInfo.pVertexBindingDescriptions = vertexBindings.Pin ();
+ vertInputInfo.vertexAttributeDescriptionCount = (uint)vertexAttributes.Count;
+ vertInputInfo.pVertexAttributeDescriptions = vertexAttributes.Pin ();
- //local copy of class fiels whose addresses are requested
- VkPipelineInputAssemblyStateCreateInfo sInputAssembly = inputAssemblyState;
- VkPipelineRasterizationStateCreateInfo sRasterization = rasterizationState;
- VkPipelineMultisampleStateCreateInfo sMultisample = multisampleState;
- VkPipelineViewportStateCreateInfo sViewport = viewportState;
- VkPipelineDepthStencilStateCreateInfo sDepthStencil = depthStencilState;
+ VkGraphicsPipelineCreateInfo info = VkGraphicsPipelineCreateInfo.New ();
+ info.renderPass = RenderPass.handle;
+ info.layout = Layout.handle;
+ info.pVertexInputState = vertInputInfo.Pin ();
+ info.pInputAssemblyState = inputAssemblyState.Pin ();
+ info.pRasterizationState = rasterizationState.Pin ();
+ info.pColorBlendState = colorBlendInfo.Pin ();
+ info.pMultisampleState = multisampleState.Pin ();
+ info.pViewportState = viewportState.Pin ();
+ info.pDepthStencilState = depthStencilState.Pin ();
+ info.pDynamicState = dynStatesInfo.Pin ();
+ info.stageCount = (uint)shaders.Count;
+ info.pStages = shaderStages.Pin ();
- info.pVertexInputState = &vertInputInfo;
- info.pInputAssemblyState = &sInputAssembly;
- info.pRasterizationState = &sRasterization;
- info.pColorBlendState = &colorBlendInfo;
- info.pMultisampleState = &sMultisample;
- info.pViewportState = &sViewport;
- info.pDepthStencilState = &sDepthStencil;
- info.pDynamicState = &dynStatesInfo;
- info.stageCount = (uint)shaders.Count;
- info.pStages = (VkPipelineShaderStageCreateInfo*)shaderStages.Data.ToPointer();
+ Utils.CheckResult (vkCreateGraphicsPipelines (dev.VkDev, VkPipelineCache.Null, 1, ref info, IntPtr.Zero, out handle));
- Utils.CheckResult (vkCreateGraphicsPipelines (dev.VkDev, VkPipelineCache.Null, 1, ref info, IntPtr.Zero, out handle));
+ for (int i = 0; i < shaders.Count; i++)
+ dev.DestroyShaderModule (shaderStages[i].module);
- for (int i = 0; i < shaders.Count; i++)
- dev.DestroyShaderModule (shaderStages[i].module);
+ vertInputInfo.Unpin ();
+ inputAssemblyState.Unpin ();
+ rasterizationState.Unpin ();
+ colorBlendInfo.Unpin ();
+ multisampleState.Unpin ();
+ viewportState.Unpin ();
+ depthStencilState.Unpin ();
+ dynStatesInfo.Unpin ();
+ shaderStages.Unpin ();
- shaderStages.Dispose ();
+ vertexAttributes.Unpin ();
+ vertexBindings.Unpin ();
+ dynamicStates.Unpin ();
+ blendAttachments.Unpin ();
+ }
+ base.Activate ();
}
public void Bind (CommandBuffer cmd) {
vkCmdBindPipeline (cmd.Handle, bindPoint, handle);
}
- #region IDisposable Support
- private bool isDisposed = false; // Pour détecter les appels redondants
- protected virtual void Dispose (bool disposing) {
- if (!isDisposed) {
- if (disposing) {
- blendAttachments.Dispose ();
- dynamicStates.Dispose ();
- vertexBindings.Dispose ();
- vertexAttributes.Dispose ();
- RenderPass.Dispose ();
- Layout.Dispose ();
- } else
- System.Diagnostics.Debug.WriteLine ("A Pipeline has not been disposed.");
+ #region IDisposable Support
+ protected override void Dispose (bool disposing) {
+ if (disposing) {
+ RenderPass.Dispose ();
+ Layout.Dispose ();
+ }else
+ System.Diagnostics.Debug.WriteLine ("VKE Activable object disposed by finalizer");
+ if (state == ActivableState.Activated)
VulkanNative.vkDestroyPipeline (dev.VkDev, handle, IntPtr.Zero);
- isDisposed = true;
- }
- }
-
- ~Pipeline () {
- Dispose (false);
- }
- public void Dispose () {
- Dispose (true);
- GC.SuppressFinalize (this);
+ base.Dispose (disposing);
}
#endregion
}
diff --git a/vke/src/PipelineConfig.cs b/vke/src/PipelineConfig.cs
new file mode 100644
index 0000000..09b500c
--- /dev/null
+++ b/vke/src/PipelineConfig.cs
@@ -0,0 +1,163 @@
+////
+//// FrameBuffer.cs
+////
+//// 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.
+//using System;
+//using System.Collections.Generic;
+//using System.Runtime.InteropServices;
+//using Vulkan;
+//using static Vulkan.VulkanNative;
+
+//namespace VKE {
+// public class PipelineConfig {
+// VkPipelineBindPoint bindPoint = VkPipelineBindPoint.Graphics;
+// VkPipelineInputAssemblyStateCreateInfo inputAssemblyState = VkPipelineInputAssemblyStateCreateInfo.New ();
+// VkPipelineRasterizationStateCreateInfo rasterizationState = VkPipelineRasterizationStateCreateInfo.New ();
+// VkPipelineViewportStateCreateInfo viewportState = VkPipelineViewportStateCreateInfo.New ();
+// public VkPipelineDepthStencilStateCreateInfo depthStencilState = VkPipelineDepthStencilStateCreateInfo.New ();
+// public VkPipelineMultisampleStateCreateInfo multisampleState = VkPipelineMultisampleStateCreateInfo.New ();
+
+// NativeList<VkPipelineColorBlendAttachmentState> blendAttachments = new NativeList<VkPipelineColorBlendAttachmentState>();
+// NativeList<VkDynamicState> dynamicStates = new NativeList<VkDynamicState> ();
+// public NativeList<VkVertexInputBindingDescription> vertexBindings = new NativeList<VkVertexInputBindingDescription> ();
+// public NativeList<VkVertexInputAttributeDescription> vertexAttributes = new NativeList<VkVertexInputAttributeDescription> ();
+// public List<ShaderInfo> shaders = new List<ShaderInfo>();
+
+// public PipelineLayout Layout;
+
+// public VkSampleCountFlags Samples {
+// get { return multisampleState.rasterizationSamples; }
+// }
+
+// public RenderPass RenderPass { get; private set; }
+
+// public void SetVertexAttributes (uint binding, params VkFormat[] attribsDesc) {
+// uint offset = 0;
+
+// for (uint i = 0; i < attribsDesc.Length; i++) {
+// vertexAttributes.Add (new VkVertexInputAttributeDescription (binding, i, attribsDesc[i], offset));
+// VkFormatSize fs;
+// Utils.vkGetFormatSize (attribsDesc[i], out fs);
+// offset += fs.blockSizeInBits/8;
+// }
+// }
+// public void AddVertexBinding (uint binding, uint stride, VkVertexInputRate inputRate = VkVertexInputRate.Vertex) {
+// vertexBindings.Add (new VkVertexInputBindingDescription (binding, stride, inputRate));
+// }
+// public void AddVertexBinding<T> (uint binding, VkVertexInputRate inputRate = VkVertexInputRate.Vertex) {
+// vertexBindings.Add (new VkVertexInputBindingDescription (binding, (uint)Marshal.SizeOf<T> (), inputRate));
+// }
+// public void AddShader (VkShaderStageFlags _stageFlags, string _spirvPath, string _entryPoint = "main") {
+// shaders.Add (new ShaderInfo (_stageFlags, _spirvPath, _entryPoint));
+// }
+// /// <summary>
+// /// Create a new Pipeline with supplied RenderPass
+// /// </summary>
+// public PipelineConfig (Device dev, RenderPass renderPass, VkPrimitiveTopology topology = VkPrimitiveTopology.TriangleList,
+// VkSampleCountFlags samples = VkSampleCountFlags.Count1)
+// {
+
+// RenderPass = renderPass;
+// RenderPass.references++;
+
+// inputAssemblyState.topology = topology;
+
+// rasterizationState.polygonMode = VkPolygonMode.Fill;
+// rasterizationState.cullMode = (uint)VkCullModeFlags.None;
+// rasterizationState.frontFace = VkFrontFace.CounterClockwise;
+// rasterizationState.depthClampEnable = False;
+// rasterizationState.rasterizerDiscardEnable = False;
+// rasterizationState.depthBiasEnable = False;
+// rasterizationState.lineWidth = 1.0f;
+
+// viewportState.viewportCount = 1;
+// viewportState.scissorCount = 1;
+
+// blendAttachments.Add (new VkPipelineColorBlendAttachmentState {
+// colorWriteMask = VkColorComponentFlags.R | VkColorComponentFlags.G | VkColorComponentFlags.B | VkColorComponentFlags.A,
+// blendEnable = False
+// });
+
+// dynamicStates.Add (VkDynamicState.Viewport);
+// dynamicStates.Add (VkDynamicState.Scissor);
+
+// depthStencilState.depthTestEnable = True;
+// depthStencilState.depthWriteEnable = True;
+// depthStencilState.depthCompareOp = VkCompareOp.LessOrEqual;
+// depthStencilState.depthBoundsTestEnable = False;
+// depthStencilState.back.failOp = VkStencilOp.Keep;
+// depthStencilState.back.passOp = VkStencilOp.Keep;
+// depthStencilState.back.compareOp = VkCompareOp.Always;
+// depthStencilState.stencilTestEnable = False;
+// depthStencilState.front = depthStencilState.back;
+
+// multisampleState.rasterizationSamples = samples;
+// }
+
+// /// <summary>
+// /// Create a new pipeline and the default renderpass for it
+// /// </summary>
+// public PipelineConfig (Device dev, VkFormat colorFormat, VkFormat depthFormat,
+// VkPrimitiveTopology topology = VkPrimitiveTopology.TriangleList,
+// VkSampleCountFlags samples = VkSampleCountFlags.Count1)
+// : this (dev, new RenderPass (dev, colorFormat, depthFormat, samples), topology,samples)
+// {
+// }
+
+// public unsafe void Activate () {
+
+// }
+
+// public void Bind (CommandBuffer cmd) {
+// vkCmdBindPipeline (cmd.Handle, bindPoint, handle);
+// }
+// #region IDisposable Support
+// private bool isDisposed = false; // Pour détecter les appels redondants
+
+// protected virtual void Dispose (bool disposing) {
+// if (!isDisposed) {
+// if (disposing) {
+// blendAttachments.Dispose ();
+// dynamicStates.Dispose ();
+// vertexBindings.Dispose ();
+// vertexAttributes.Dispose ();
+// RenderPass.Dispose ();
+// Layout.Dispose ();
+// } else
+// System.Diagnostics.Debug.WriteLine ("A Pipeline has not been disposed.");
+// VulkanNative.vkDestroyPipeline (dev.VkDev, handle, IntPtr.Zero);
+// isDisposed = true;
+// }
+// }
+
+// ~PipelineConfig () {
+// Dispose (false);
+// }
+// public void Dispose () {
+// Dispose (true);
+// GC.SuppressFinalize (this);
+// }
+// #endregion
+// }
+//}
diff --git a/vke/src/PipelineLayout.cs b/vke/src/PipelineLayout.cs
index 68f7d4b..c1afc79 100644
--- a/vke/src/PipelineLayout.cs
+++ b/vke/src/PipelineLayout.cs
@@ -30,18 +30,13 @@ using Vulkan;
using static Vulkan.VulkanNative;
namespace VKE {
-
- public class PipelineLayout : IDisposable {
- internal uint references;
+ public sealed class PipelineLayout : Activable {
internal VkPipelineLayout handle;
- internal Device dev;
public List<DescriptorSetLayout> DescriptorSetLayouts = new List<DescriptorSetLayout> ();
- public NativeList<VkPushConstantRange> PushConstantRanges = new NativeList<VkPushConstantRange> ();
+ public List<VkPushConstantRange> PushConstantRanges = new List<VkPushConstantRange> ();
- public PipelineLayout (Device device) {
- dev = device;
- }
+ public PipelineLayout (Device device) : base (device) { }
public PipelineLayout (Device device, VkPushConstantRange pushConstantRange, params DescriptorSetLayout[] descriptorSetLayouts)
: this (device, descriptorSetLayouts) {
PushConstantRanges.Add (pushConstantRange);
@@ -61,52 +56,33 @@ namespace VKE {
foreach (VkPushConstantRange pcr in pushConstantRanges)
PushConstantRanges.Add (pcr);
}
- public PipelineLayout Activate () {
- if (isDisposed) {
- isDisposed = false;
- GC.ReRegisterForFinalize (this);
- PushConstantRanges = new NativeList<VkPushConstantRange> ();
- }
- VkPipelineLayoutCreateInfo info = VkPipelineLayoutCreateInfo.New ();
- VkDescriptorSetLayout[] dsls = DescriptorSetLayouts.Select (dsl => dsl.handle).ToArray ();
- if (dsls.Length > 0) {
- info.setLayoutCount = (uint)dsls.Length;
- info.pSetLayouts = dsls.Pin ();
- }
- if (PushConstantRanges.Count > 0) {
- info.pushConstantRangeCount = (uint)PushConstantRanges.Count;
- info.pPushConstantRanges = PushConstantRanges.Data;
+ public override void Activate () {
+ if (state != ActivableState.Activated) {
+ VkPipelineLayoutCreateInfo info = VkPipelineLayoutCreateInfo.New ();
+ VkDescriptorSetLayout[] dsls = DescriptorSetLayouts.Select (dsl => dsl.handle).ToArray ();
+
+ if (dsls.Length > 0) {
+ info.setLayoutCount = (uint)dsls.Length;
+ info.pSetLayouts = dsls.Pin ();
+ }
+ if (PushConstantRanges.Count > 0) {
+ info.pushConstantRangeCount = (uint)PushConstantRanges.Count;
+ info.pPushConstantRanges = PushConstantRanges.Pin();
+ }
+ Utils.CheckResult (vkCreatePipelineLayout (dev.VkDev, ref info, IntPtr.Zero, out handle));
+ dsls.Unpin ();
+ PushConstantRanges.Unpin ();
}
- Utils.CheckResult (vkCreatePipelineLayout (dev.VkDev, ref info, IntPtr.Zero, out handle));
- dsls.Unpin ();
- return this;
+ base.Activate ();
}
#region IDisposable Support
- private bool isDisposed = false; // Pour détecter les appels redondants
-
- protected virtual void Dispose (bool disposing) {
- if (!isDisposed) {
- if (disposing) {
- PushConstantRanges.Dispose ();
- } else
- System.Diagnostics.Debug.WriteLine ("One Pipeline layout was not disposed");
-
+ protected override void Dispose (bool disposing) {
+ if (!disposing)
+ System.Diagnostics.Debug.WriteLine ("VKE Activable PipelineLayout disposed by finalizer");
+ if (state == ActivableState.Activated)
vkDestroyPipelineLayout (dev.VkDev, handle, IntPtr.Zero);
- isDisposed = true;
- }
- }
-
- ~PipelineLayout() {
- Dispose(false);
- }
- public void Dispose () {
- if (references>0)
- references--;
- if (references>0)
- return;
- Dispose (true);
- GC.SuppressFinalize(this);
+ base.Dispose (disposing);
}
#endregion
}
diff --git a/vke/src/RenderPass.cs b/vke/src/RenderPass.cs
index 8e73e10..809edf3 100644
--- a/vke/src/RenderPass.cs
+++ b/vke/src/RenderPass.cs
@@ -30,16 +30,75 @@ using Vulkan;
using static Vulkan.VulkanNative;
namespace VKE {
- public class RenderPass : IDisposable {
- internal uint references;
- internal VkRenderPass handle;
- internal Device dev;
-
- internal NativeList<VkAttachmentDescription> attachments = new NativeList<VkAttachmentDescription> ();
- public NativeList<VkClearValue> ClearValues = new NativeList<VkClearValue> ();
+ public class RenderPass : Activable {
+ internal VkRenderPass handle;
+ internal List<VkAttachmentDescription> attachments = new List<VkAttachmentDescription> ();
+ public List<VkClearValue> ClearValues = new List<VkClearValue> ();
internal List<SubPass> subpasses = new List<SubPass> ();
- NativeList<VkSubpassDependency> dependencies = new NativeList<VkSubpassDependency> ();
+ List<VkSubpassDependency> dependencies = new List<VkSubpassDependency> ();
+
+ #region CTORS
+ public RenderPass (Device device) : base(device) { }
+
+ /// <summary>
+ /// Create default renderpass with one color and one depth attachments
+ /// </summary>
+ public RenderPass (Device device, VkFormat colorFormat, VkFormat depthFormat, VkSampleCountFlags samples = VkSampleCountFlags.Count1)
+ : this (device){
+
+ AddAttachment (colorFormat, (samples == VkSampleCountFlags.Count1) ? VkImageLayout.PresentSrcKHR : VkImageLayout.ColorAttachmentOptimal, samples);
+ AddAttachment (depthFormat, VkImageLayout.DepthStencilAttachmentOptimal, samples);
+
+ ClearValues.Add (new VkClearValue { color = new VkClearColorValue (0.0f, 0.0f, 0.2f) });
+ ClearValues.Add (new VkClearValue { depthStencil = new VkClearDepthStencilValue (1.0f, 0) });
+
+ SubPass subpass0 = new SubPass ();
+
+ subpass0.AddColorReference (0, VkImageLayout.ColorAttachmentOptimal);
+ subpass0.SetDepthReference (1, VkImageLayout.DepthStencilAttachmentOptimal);
+
+ if (samples != VkSampleCountFlags.Count1) {
+ AddAttachment (colorFormat, VkImageLayout.PresentSrcKHR, VkSampleCountFlags.Count1);
+ ClearValues.Add (new VkClearValue { color = new VkClearColorValue (0.0f, 0.0f, 0.2f) });
+ subpass0.AddResolveReference (2, VkImageLayout.ColorAttachmentOptimal);
+ }
+
+
+ AddSubpass (subpass0);
+
+ AddDependency (VulkanNative.SubpassExternal, 0,
+ VkPipelineStageFlags.BottomOfPipe, VkPipelineStageFlags.ColorAttachmentOutput,
+ VkAccessFlags.MemoryRead, VkAccessFlags.ColorAttachmentRead | VkAccessFlags.ColorAttachmentWrite);
+ AddDependency (0, 1,
+ VkPipelineStageFlags.ColorAttachmentOutput, VkPipelineStageFlags.BottomOfPipe,
+ VkAccessFlags.ColorAttachmentRead | VkAccessFlags.ColorAttachmentWrite, VkAccessFlags.MemoryRead);
+ }
+ #endregion
+
+ public override void Activate () {
+ if (state != ActivableState.Activated) {
+ List<VkSubpassDescription> spDescs = new List<VkSubpassDescription> ();
+ foreach (SubPass sp in subpasses)
+ spDescs.Add (sp.SubpassDescription);
+
+ VkRenderPassCreateInfo renderPassInfo = VkRenderPassCreateInfo.New ();
+ renderPassInfo.attachmentCount = (uint)attachments.Count;
+ renderPassInfo.pAttachments = attachments.Pin ();
+ renderPassInfo.subpassCount = (uint)spDescs.Count;
+ renderPassInfo.pSubpasses = spDescs.Pin ();
+ renderPassInfo.dependencyCount = (uint)dependencies.Count;
+ renderPassInfo.pDependencies = dependencies.Pin ();
+
+ handle = dev.CreateRenderPass (renderPassInfo);
+
+ attachments.Unpin ();
+ spDescs.Unpin ();
+ dependencies.Unpin ();
+ }
+ base.Activate ();
+ }
+
public void AddAttachment (VkFormat format,
VkImageLayout finalLayout, VkSampleCountFlags samples = VkSampleCountFlags.Count1,
@@ -93,72 +152,6 @@ namespace VKE {
public void AddSubpass (SubPass subPass) {
subpasses.Add (subPass);
}
- public RenderPass (Device device) {
- dev = device;
- }
- /// <summary>
- /// Create default renderpass with one color and one depth attachments
- /// </summary>
- public RenderPass (Device device, VkFormat colorFormat, VkFormat depthFormat, VkSampleCountFlags samples = VkSampleCountFlags.Count1)
- : this (device){
-
- AddAttachment (colorFormat, (samples == VkSampleCountFlags.Count1) ? VkImageLayout.PresentSrcKHR : VkImageLayout.ColorAttachmentOptimal, samples);
- AddAttachment (depthFormat, VkImageLayout.DepthStencilAttachmentOptimal, samples);
-
- ClearValues.Add (new VkClearValue { color = new VkClearColorValue (0.0f, 0.0f, 0.2f) });
- ClearValues.Add (new VkClearValue { depthStencil = new VkClearDepthStencilValue (1.0f, 0) });
-
- SubPass subpass0 = new SubPass ();
-
- subpass0.AddColorReference (0, VkImageLayout.ColorAttachmentOptimal);
- subpass0.SetDepthReference (1, VkImageLayout.DepthStencilAttachmentOptimal);
-
- if (samples != VkSampleCountFlags.Count1) {
- AddAttachment (colorFormat, VkImageLayout.PresentSrcKHR, VkSampleCountFlags.Count1);
- ClearValues.Add (new VkClearValue { color = new VkClearColorValue (0.0f, 0.0f, 0.2f) });
- subpass0.AddResolveReference (2, VkImageLayout.ColorAttachmentOptimal);
- }
-
-
- AddSubpass (subpass0);
-
- AddDependency (VulkanNative.SubpassExternal, 0,
- VkPipelineStageFlags.BottomOfPipe, VkPipelineStageFlags.ColorAttachmentOutput,
- VkAccessFlags.MemoryRead, VkAccessFlags.ColorAttachmentRead | VkAccessFlags.ColorAttachmentWrite);
- AddDependency (0, 1,
- VkPipelineStageFlags.ColorAttachmentOutput, VkPipelineStageFlags.BottomOfPipe,
- VkAccessFlags.ColorAttachmentRead | VkAccessFlags.ColorAttachmentWrite, VkAccessFlags.MemoryRead);
-
- Activate ();
- }
- public void Activate () {
- if (isDisposed) {
- GC.ReRegisterForFinalize (this);
- isDisposed = false;
- }
- using (NativeList<VkSubpassDescription> spDescs = new NativeList<VkSubpassDescription> ((uint)subpasses.Count)) {
- foreach (SubPass sp in subpasses)
- spDescs.Add (sp.SubpassDescription);
-
- VkRenderPassCreateInfo renderPassInfo = VkRenderPassCreateInfo.New ();
- renderPassInfo.attachmentCount = attachments.Count;
- renderPassInfo.pAttachments = attachments.Data;
- renderPassInfo.subpassCount = spDescs.Count;
- renderPassInfo.pSubpasses = spDescs.Data;
- renderPassInfo.dependencyCount = dependencies.Count;
- renderPassInfo.pDependencies = dependencies.Data;
-
- handle = dev.CreateRenderPass (renderPassInfo);
- }
- }
-
- //public Framebuffer CreateFramebuffer (SwapChain swapChain) {
- // Framebuffer fb;
-
- // return fb;
- //}
-
-
/// <summary>
/// Begin Render pass with framebuffer extent dimensions
/// </summary>
@@ -174,42 +167,25 @@ namespace VKE {
info.renderPass = handle;
info.renderArea.extent.width = width;
info.renderArea.extent.height = height;
- info.clearValueCount = ClearValues.Count;
- info.pClearValues = (VkClearValue*) ClearValues.Data.ToPointer();
+ info.clearValueCount = (uint)ClearValues.Count;
+ info.pClearValues = ClearValues.Pin ();
info.framebuffer = frameBuffer.handle;
vkCmdBeginRenderPass (cmd.Handle, ref info, VkSubpassContents.Inline);
+
+ ClearValues.Unpin ();
}
public void End (CommandBuffer cmd) {
vkCmdEndRenderPass (cmd.Handle);
}
#region IDisposable Support
- private bool isDisposed = false; // Pour détecter les appels redondants
-
- protected virtual void Dispose (bool disposing) {
- if (!isDisposed) {
- if (disposing) {
- attachments.Dispose ();
- ClearValues.Dispose ();
- dependencies.Dispose ();
- } else
- System.Diagnostics.Debug.WriteLine ("A Renderpass has not been disposed.");
+ protected override void Dispose (bool disposing) {
+ if (!disposing)
+ System.Diagnostics.Debug.WriteLine ("VKE Activable RenderPass disposed by finalizer");
+ if (state == ActivableState.Activated)
dev.DestroyRenderPass (handle);
- isDisposed = true;
- }
- }
-
- ~RenderPass () {
- Dispose (false);
- }
- public void Dispose () {
- if (references>0)
- references--;
- if (references>0)
- return;
- Dispose (true);
- GC.SuppressFinalize (this);
+ base.Dispose (disposing);
}
#endregion
}
diff --git a/vke/src/Resource.cs b/vke/src/Resource.cs
index 2c87e50..22b7375 100644
--- a/vke/src/Resource.cs
+++ b/vke/src/Resource.cs
@@ -6,9 +6,7 @@ using Vulkan;
using static Vulkan.VulkanNative;
namespace VKE {
- public abstract class Resource : IDisposable {
- internal uint references;
- protected Device dev;
+ public abstract class Resource : Activable {
protected VkDeviceMemory vkMemory;
protected UInt64 deviceMemSize;
protected IntPtr mappedData;
@@ -17,21 +15,13 @@ namespace VKE {
public IntPtr MappedData => mappedData;
public UInt64 AllocatedDeviceMemorySize => deviceMemSize;
- protected Resource (Device device, VkMemoryPropertyFlags memoryFlags) {
- dev = device;
+ protected Resource (Device device, VkMemoryPropertyFlags memoryFlags) : base (device) {
MemoryFlags = memoryFlags;
}
protected abstract VkMemoryRequirements getMemoryRequirements ();
protected abstract void bindMemory (ulong offset);
- //memory is not allocated and bindind in here because Activate may be called in ctor of
- //derrived classes, and appropriate virtual allocateMemory and bindMemory must be called
- public virtual void Activate () {
- if (isDisposed)
- GC.ReRegisterForFinalize (this);
- }
-
protected void allocateMemory () {
VkMemoryRequirements memReqs = getMemoryRequirements ();
VkMemoryAllocateInfo memInfo = VkMemoryAllocateInfo.New ();
@@ -68,34 +58,16 @@ namespace VKE {
vkFlushMappedMemoryRanges (dev.VkDev, 1, ref range);
}
- #region IDisposable Support
- protected bool isDisposed;
-
- protected virtual void Dispose (bool disposing) {
- if (!isDisposed) {
- if (disposing) {
- // TODO: supprimer l'état managé (objets managés).
- }
-
- if (mappedData != IntPtr.Zero)
- Unmap ();
- vkFreeMemory (dev.VkDev, vkMemory, IntPtr.Zero);
-
- isDisposed = true;
- }
- }
-
- ~Resource () {
- Dispose (false);
- }
-
- public void Dispose () {
- if (references>0)
- references--;
- if (references>0)
- return;
- Dispose (true);
- GC.SuppressFinalize (this);
+ #region IDisposable Support
+ protected override void Dispose (bool disposing) {
+ if (!disposing)
+ System.Diagnostics.Debug.WriteLine ("VKE Activable object disposed by finalizer");
+ if (state == ActivableState.Activated) {
+ if (mappedData != IntPtr.Zero)
+ Unmap ();
+ vkFreeMemory (dev.VkDev, vkMemory, IntPtr.Zero);
+ }
+ base.Dispose (disposing);
}
#endregion
}
diff --git a/vke/src/ShaderInfo.cs b/vke/src/ShaderInfo.cs
new file mode 100644
index 0000000..f346195
--- /dev/null
+++ b/vke/src/ShaderInfo.cs
@@ -0,0 +1,69 @@
+//
+// FrameBuffer.cs
+//
+// 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.
+using System;
+using System.Collections.Generic;
+using System.Runtime.InteropServices;
+using Vulkan;
+using static Vulkan.VulkanNative;
+
+namespace VKE {
+ public class ShaderInfo : IDisposable {
+ public VkShaderStageFlags StageFlags;
+ public string SpirvPath;
+ public FixedUtf8String EntryPoint;
+
+ public ShaderInfo (VkShaderStageFlags _stageFlags, string _spirvPath, string _entryPoint = "main") {
+ StageFlags = _stageFlags;
+ SpirvPath = _spirvPath;
+ EntryPoint = new FixedUtf8String (_entryPoint);
+ }
+
+ public VkPipelineShaderStageCreateInfo GetStageCreateInfo (Device dev) {
+ return new VkPipelineShaderStageCreateInfo {
+ sType = VkStructureType.PipelineShaderStageCreateInfo,
+ stage = StageFlags,
+ pName = EntryPoint,
+ module = dev.LoadSPIRVShader (SpirvPath),
+ };
+ }
+
+ #region IDisposable Support
+ private bool disposedValue = false; // Pour détecter les appels redondants
+
+ protected virtual void Dispose (bool disposing) {
+ if (!disposedValue) {
+ if (disposing)
+ EntryPoint.Dispose ();
+
+ disposedValue = true;
+ }
+ }
+ public void Dispose () {
+ Dispose (true);
+ }
+ #endregion
+ }
+}