diff options
| author | Jean-Philippe Bruyère <jp_bruyere@hotmail.com> | 2019-04-26 01:53:07 +0200 |
|---|---|---|
| committer | Jean-Philippe Bruyère <jp_bruyere@hotmail.com> | 2019-04-26 01:53:07 +0200 |
| commit | 568219e7719bfaf076ba23b539dd6ee7f647e273 (patch) | |
| tree | 5b06297bb69dc2d511917f5d22f967028aa01077 | |
| parent | 01ea60eb8fc7b7a30f388f7be6e7c401ee94e441 (diff) | |
pipeline cache
| -rw-r--r-- | samples/deferred/EnvironmentPipeline.cs | 4 | ||||
| -rw-r--r-- | samples/deferred/main.cs | 10 | ||||
| -rw-r--r-- | samples/pbrSashaWillem/EnvironmentPipeline.cs | 4 | ||||
| -rw-r--r-- | samples/pbrSashaWillem/PbrPipeline.cs | 4 | ||||
| -rw-r--r-- | vke/src/ComputePipeline.cs | 9 | ||||
| -rw-r--r-- | vke/src/DescriptorPool.cs | 6 | ||||
| -rw-r--r-- | vke/src/GraphicPipeline.cs | 10 | ||||
| -rw-r--r-- | vke/src/GraphicPipelineConfig.cs | 2 | ||||
| -rw-r--r-- | vke/src/Pipeline.cs | 5 | ||||
| -rw-r--r-- | vke/src/PipelineCache.cs | 114 | ||||
| -rw-r--r-- | vke/src/SpecializationConstant.cs | 20 |
11 files changed, 163 insertions, 25 deletions
diff --git a/samples/deferred/EnvironmentPipeline.cs b/samples/deferred/EnvironmentPipeline.cs index 68128cc..909ee4a 100644 --- a/samples/deferred/EnvironmentPipeline.cs +++ b/samples/deferred/EnvironmentPipeline.cs @@ -17,8 +17,8 @@ namespace CVKL { public int debugMip = 0; public int debugFace = 0; - public EnvironmentCube (DescriptorSet dsSkybox, PipelineLayout plLayout, Queue staggingQ, RenderPass renderPass) - : base (renderPass, "EnvCube pipeline") { + public EnvironmentCube (DescriptorSet dsSkybox, PipelineLayout plLayout, Queue staggingQ, RenderPass renderPass, PipelineCache cache = null) + : base (renderPass, cache, "EnvCube pipeline") { using (CommandPool cmdPool = new CommandPool (staggingQ.Dev, staggingQ.index)) { diff --git a/samples/deferred/main.cs b/samples/deferred/main.cs index 1b1d720..db60521 100644 --- a/samples/deferred/main.cs +++ b/samples/deferred/main.cs @@ -79,6 +79,7 @@ namespace deferred { DescriptorSetLayout descLayoutMain, descLayoutTextures, descLayoutGBuff; DescriptorSet dsMain, dsGBuff; + PipelineCache pipelineCache; Pipeline gBuffPipeline, composePipeline, toneMappingPipeline, debugPipeline; HostBuffer uboMats; @@ -97,6 +98,8 @@ namespace deferred { const int SP_TONE_MAPPING = 3; Program () { + pipelineCache = new PipelineCache (dev); + camera = new Camera (Utils.DegreesToRadians (45f), 1f, 0.1f, 16f); init (); @@ -205,7 +208,7 @@ namespace deferred { cfg.multisampleState.sampleShadingEnable = true; cfg.multisampleState.minSampleShading = 0.5f; } - + cfg.Cache = pipelineCache; cfg.Layout = new PipelineLayout (dev, descLayoutMain, descLayoutTextures, descLayoutGBuff); cfg.Layout.AddPushConstants ( new VkPushConstantRange (VkShaderStageFlags.Vertex, (uint)Marshal.SizeOf<Matrix4x4> ()), @@ -544,6 +547,10 @@ namespace deferred { camera.Type = Camera.CamType.FirstPerson; Console.WriteLine ($"camera type = {camera.Type}"); break; + case Key.S: + pipelineCache.Save (); + Console.WriteLine ($"Pipeline Cache saved."); + break; default: base.onKeyDown (key, scanCode, modifiers); return; @@ -579,6 +586,7 @@ namespace deferred { envCube.Dispose (); descriptorPool.Dispose (); + pipelineCache.Dispose (); } } diff --git a/samples/pbrSashaWillem/EnvironmentPipeline.cs b/samples/pbrSashaWillem/EnvironmentPipeline.cs index c12aa6e..010d21d 100644 --- a/samples/pbrSashaWillem/EnvironmentPipeline.cs +++ b/samples/pbrSashaWillem/EnvironmentPipeline.cs @@ -18,8 +18,8 @@ namespace CVKL { public int debugMip = -1; public int debugFace = 0; - public EnvironmentCube (DescriptorSet dsSkybox, PipelineLayout plLayout, Queue staggingQ, RenderPass renderPass) - : base (renderPass, "EnvCube pipeline") { + public EnvironmentCube (DescriptorSet dsSkybox, PipelineLayout plLayout, Queue staggingQ, RenderPass renderPass, PipelineCache pipelineCache = null) + : base (renderPass, pipelineCache, "EnvCube pipeline") { using (CommandPool cmdPool = new CommandPool (staggingQ.Dev, staggingQ.index)) { diff --git a/samples/pbrSashaWillem/PbrPipeline.cs b/samples/pbrSashaWillem/PbrPipeline.cs index b7df5a1..20a8ae1 100644 --- a/samples/pbrSashaWillem/PbrPipeline.cs +++ b/samples/pbrSashaWillem/PbrPipeline.cs @@ -40,8 +40,8 @@ namespace CVKL { public PbrModel2 model; public EnvironmentCube envCube; - public PBRPipeline (Queue staggingQ, RenderPass renderPass, Image uiImage) : - base (renderPass, "pbr pipeline") { + public PBRPipeline (Queue staggingQ, RenderPass renderPass, Image uiImage, PipelineCache pipelineCache = null) : + base (renderPass, pipelineCache, "pbr pipeline") { descriptorPool = new DescriptorPool (Dev, 2, new VkDescriptorPoolSize (VkDescriptorType.UniformBuffer, 2), diff --git a/vke/src/ComputePipeline.cs b/vke/src/ComputePipeline.cs index 323006a..e57a7d0 100644 --- a/vke/src/ComputePipeline.cs +++ b/vke/src/ComputePipeline.cs @@ -33,12 +33,12 @@ namespace CVKL { public string SpirVPath; #region CTORS - public ComputePipeline (Device dev, string name = "compute pipeline") : base (dev, name) { + public ComputePipeline (Device dev, PipelineCache cache = null, string name = "compute pipeline") : base (dev, cache, name) { } /// <summary> - /// Create a new Pipeline with supplied RenderPass + /// Create a new Pipeline with supplied PipelineLayout /// </summary> - public ComputePipeline (PipelineLayout layout, string spirvPath, string name = "pipeline") : base(layout.Dev, name) + public ComputePipeline (PipelineLayout layout, string spirvPath, PipelineCache cache = null, string name = "pipeline") : base(layout.Dev, cache, name) { SpirVPath = spirvPath; this.layout = layout; @@ -50,6 +50,7 @@ namespace CVKL { public override void Activate () { if (state != ActivableState.Activated) { layout.Activate (); + Cache?.Activate (); using (ShaderInfo shader = new ShaderInfo (VkShaderStageFlags.Compute, SpirVPath)) { VkComputePipelineCreateInfo info = VkComputePipelineCreateInfo.New (); @@ -58,7 +59,7 @@ namespace CVKL { info.basePipelineHandle = 0; info.basePipelineIndex = 0; - Utils.CheckResult (Vk.vkCreateComputePipelines (Dev.VkDev, VkPipelineCache.Null, 1, ref info, IntPtr.Zero, out handle)); + Utils.CheckResult (Vk.vkCreateComputePipelines (Dev.VkDev, Cache == null ? VkPipelineCache.Null : Cache.handle, 1, ref info, IntPtr.Zero, out handle)); Dev.DestroyShaderModule (info.stage.module); } diff --git a/vke/src/DescriptorPool.cs b/vke/src/DescriptorPool.cs index 05c1685..bd5a3d8 100644 --- a/vke/src/DescriptorPool.cs +++ b/vke/src/DescriptorPool.cs @@ -29,7 +29,7 @@ using VK; using static VK.Vk; namespace CVKL { - public class DescriptorPool : Activable { + public sealed class DescriptorPool : Activable { internal VkDescriptorPool handle; public readonly uint MaxSets; @@ -72,7 +72,7 @@ namespace CVKL { Allocate (ds); return ds; } - public unsafe void Allocate (DescriptorSet descriptorSet) { + public void Allocate (DescriptorSet descriptorSet) { VkDescriptorSetAllocateInfo allocInfo = VkDescriptorSetAllocateInfo.New(); allocInfo.descriptorPool = handle; allocInfo.descriptorSetCount = (uint)descriptorSet.descriptorSetLayouts.Count; @@ -104,7 +104,7 @@ namespace CVKL { #region IDisposable Support protected override void Dispose (bool disposing) { if (!disposing) - System.Diagnostics.Debug.WriteLine ("VKE DescriptorPool disposed by finalizer"); + System.Diagnostics.Debug.WriteLine ($"CVKL DescriptorPool '{name}' disposed by finalizer"); if (state == ActivableState.Activated) vkDestroyDescriptorPool (Dev.VkDev, handle, IntPtr.Zero); base.Dispose (disposing); diff --git a/vke/src/GraphicPipeline.cs b/vke/src/GraphicPipeline.cs index 5a84eb1..562e4fa 100644 --- a/vke/src/GraphicPipeline.cs +++ b/vke/src/GraphicPipeline.cs @@ -35,15 +35,14 @@ namespace CVKL { public VkSampleCountFlags Samples => RenderPass.Samples; #region CTORS - protected GraphicPipeline (RenderPass renderPass, string name = "graphic pipeline") : base(renderPass.Dev, name) { + protected GraphicPipeline (RenderPass renderPass, PipelineCache cache = null, string name = "graphic pipeline") : base(renderPass.Dev, cache, name) { RenderPass = renderPass; - handle.SetDebugMarkerName (Dev, name); } /// <summary> /// Create a new Pipeline with supplied RenderPass /// </summary> - public GraphicPipeline (GraphicPipelineConfig cfg, string name = "graphic pipeline") : this (cfg.RenderPass, name) + public GraphicPipeline (GraphicPipelineConfig cfg, string name = "graphic pipeline") : this (cfg.RenderPass, cfg.Cache, name) { layout = cfg.Layout; @@ -58,6 +57,7 @@ namespace CVKL { if (state != ActivableState.Activated) { Layout.Activate (); RenderPass.Activate (); + Cache?.Activate (); List<VkPipelineShaderStageCreateInfo> shaderStages = new List<VkPipelineShaderStageCreateInfo> (); foreach (ShaderInfo shader in cfg.shaders) @@ -92,7 +92,7 @@ namespace CVKL { info.pStages = shaderStages.Pin (); info.subpass = cfg.SubpassIndex; - Utils.CheckResult (vkCreateGraphicsPipelines (Dev.VkDev, VkPipelineCache.Null, 1, ref info, IntPtr.Zero, out handle)); + Utils.CheckResult (vkCreateGraphicsPipelines (Dev.VkDev, Cache == null ? VkPipelineCache.Null : Cache.handle, 1, ref info, IntPtr.Zero, out handle)); for (int i = 0; i < cfg.shaders.Count; i++) Dev.DestroyShaderModule (shaderStages[i].module); @@ -124,7 +124,7 @@ namespace CVKL { protected override void Dispose (bool disposing) { if (disposing) { - if (state == ActivableState.Activated) + if (state == ActivableState.Activated) RenderPass.Dispose (); }else System.Diagnostics.Debug.WriteLine ("GraphicPipeline disposed by finalizer"); diff --git a/vke/src/GraphicPipelineConfig.cs b/vke/src/GraphicPipelineConfig.cs index 31d9d7d..000da1a 100644 --- a/vke/src/GraphicPipelineConfig.cs +++ b/vke/src/GraphicPipelineConfig.cs @@ -34,7 +34,7 @@ namespace CVKL { public uint SubpassIndex; public PipelineLayout Layout; public RenderPass RenderPass; - + public PipelineCache Cache; public VkPipelineBindPoint bindPoint = VkPipelineBindPoint.Graphics; public VkPipelineInputAssemblyStateCreateInfo inputAssemblyState = VkPipelineInputAssemblyStateCreateInfo.New(); public VkPipelineRasterizationStateCreateInfo rasterizationState = VkPipelineRasterizationStateCreateInfo.New(); diff --git a/vke/src/Pipeline.cs b/vke/src/Pipeline.cs index 4eba418..9a6b3aa 100644 --- a/vke/src/Pipeline.cs +++ b/vke/src/Pipeline.cs @@ -31,6 +31,7 @@ namespace CVKL { public abstract class Pipeline : Activable { protected VkPipeline handle; protected PipelineLayout layout; + protected PipelineCache Cache; public VkPipeline Handle => handle; public PipelineLayout Layout => layout; @@ -38,7 +39,8 @@ namespace CVKL { protected readonly VkPipelineBindPoint bindPoint; #region CTORS - protected Pipeline (Device dev, string name = "custom pipeline") : base(dev, name) { + protected Pipeline (Device dev, PipelineCache cache = null, string name = "custom pipeline") : base(dev, name) { + this.Cache = cache; } #endregion @@ -52,6 +54,7 @@ namespace CVKL { if (state == ActivableState.Activated) { if (disposing) { layout.Dispose (); + Cache?.Dispose (); } else System.Diagnostics.Debug.WriteLine ($"Pipeline '{name}' disposed by finalizer"); diff --git a/vke/src/PipelineCache.cs b/vke/src/PipelineCache.cs new file mode 100644 index 0000000..879dda6 --- /dev/null +++ b/vke/src/PipelineCache.cs @@ -0,0 +1,114 @@ +// +// SpecializationConstant.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.IO; +using System.Reflection; +using System.Runtime.InteropServices; +using VK; + +using static VK.Vk; + +namespace CVKL { + public sealed class PipelineCache : Activable { + internal VkPipelineCache handle; + readonly string globalConfigPath; + readonly string cacheFile; + + #region CTOR + public PipelineCache (Device dev, string cacheFile = "pipelines.bin", string name = "pipeline cache") : base(dev, name) { + string configRoot = Path.Combine (Environment.GetFolderPath (Environment.SpecialFolder.UserProfile), ".config"); + string appName = Assembly.GetEntryAssembly ().GetName ().Name; + globalConfigPath = Path.Combine (configRoot, appName); + + if (!Directory.Exists (globalConfigPath)) + Directory.CreateDirectory (globalConfigPath); + + this.cacheFile = cacheFile; + + Activate (); + } + #endregion + + public override void Activate () { + string path = Path.Combine (globalConfigPath, cacheFile); + + if (state != ActivableState.Activated) { + VkPipelineCacheCreateInfo info = VkPipelineCacheCreateInfo.New (); + + if (File.Exists (path)) { + using (FileStream fs = File.Open (path, FileMode.Open)) { + using (BinaryReader br = new BinaryReader (fs)) { + int length = (int)br.BaseStream.Length; + info.pInitialData = Marshal.AllocHGlobal (length); + info.initialDataSize = (UIntPtr)br.BaseStream.Length; + Marshal.Copy(br.ReadBytes (length),0, info.pInitialData, length); + } + } + } + + Utils.CheckResult (vkCreatePipelineCache (Dev.VkDev, ref info, IntPtr.Zero, out handle)); + + if (info.pInitialData != IntPtr.Zero) + Marshal.FreeHGlobal (info.pInitialData); + } + base.Activate (); + } + + protected override VkDebugMarkerObjectNameInfoEXT DebugMarkerInfo => throw new NotImplementedException (); + + public void Save () { + if (state != ActivableState.Activated) + return; + string path = Path.Combine (globalConfigPath, cacheFile); + + if (File.Exists (path)) + File.Delete (path); + + UIntPtr dataSize; + Utils.CheckResult (vkGetPipelineCacheData (Dev.VkDev, handle, out dataSize, IntPtr.Zero)); + byte[] pData = new byte[(int)dataSize]; + Utils.CheckResult (vkGetPipelineCacheData (Dev.VkDev, handle, out dataSize, pData.Pin ())); + pData.Unpin (); + + using (FileStream fs = File.Open (path, FileMode.CreateNew)) + using (BinaryWriter br = new BinaryWriter (fs)) + br.Write (pData, 0, (int)dataSize); + } + + + #region IDisposable Support + protected override void Dispose (bool disposing) { + if (!disposing) + System.Diagnostics.Debug.WriteLine ($"CVKL PipelineCache '{name}' disposed by finalizer"); + if (state == ActivableState.Activated) + vkDestroyPipelineCache (Dev.VkDev, handle, IntPtr.Zero); + base.Dispose (disposing); + } + #endregion + + } +} diff --git a/vke/src/SpecializationConstant.cs b/vke/src/SpecializationConstant.cs index adb51d9..b1ecd9e 100644 --- a/vke/src/SpecializationConstant.cs +++ b/vke/src/SpecializationConstant.cs @@ -28,7 +28,10 @@ using System.Collections.Generic; using System.Runtime.InteropServices; using VK; -namespace CVKL { +namespace CVKL { + /// <summary> + /// Hold shader specialization constant value and type + /// </summary> public class SpecializationConstant<T> : SpecializationConstant { T val; IntPtr ptr = IntPtr.Zero; @@ -48,9 +51,15 @@ namespace CVKL { public unsafe override void WriteTo (IntPtr ptr) { this.ptr = ptr; - if (typeof(T) == typeof(float)) { - float val = Convert.ToSingle(Value); - System.Buffer.MemoryCopy (&val, ptr.ToPointer (), 4, 4); + if (typeof (T) == typeof (float)) { + float v = Convert.ToSingle (Value); + System.Buffer.MemoryCopy (&v, ptr.ToPointer (), 4, 4); + } else if (typeof (T) == typeof (int) || typeof (T) == typeof (uint)) { + Marshal.WriteInt32 (ptr, Convert.ToInt32 (val)); + } else if (typeof (T) == typeof (long) || typeof (T) == typeof (ulong)) { + Marshal.WriteInt64 (ptr, Convert.ToInt64 (val)); + } else if (typeof (T) == typeof (byte)) { + Marshal.WriteByte (ptr, Convert.ToByte (val)); } } } @@ -63,6 +72,9 @@ namespace CVKL { public abstract void WriteTo (IntPtr ptr); } + /// <summary> + /// Specialization constant infos, must be disposed after pipeline creation + /// </summary> public class SpecializationInfo : IDisposable { IntPtr pData; VkSpecializationMapEntry[] entries; |