]> O.S.I.I.S - jp/crow.git/commitdiff
it's now possible to run vkvgBackend in DebugLogView on cairo
authorJean-Philippe Bruyère <jp_bruyere@hotmail.com>
Thu, 12 Aug 2021 14:22:34 +0000 (16:22 +0200)
committerJean-Philippe Bruyère <jp_bruyere@hotmail.com>
Thu, 12 Aug 2021 14:22:34 +0000 (16:22 +0200)
Crow/src/GraphicBackends/vkvg/Surface.cs
Crow/src/GraphicBackends/vkvg/VulkanContext.cs
Crow/src/Interface.cs
Samples/DebugLogAnalyzer/DebugLogAnalyzer.csproj
Samples/DebugLogAnalyzer/src/DebugInterface.cs
Samples/DebugLogAnalyzer/src/DebugInterfaceWidget.cs

index 6d7321a509fa75c9a2d7ffe6b1f922c5edd01929..dba19ca4fcd0b87bf71b77dcafd595b6173eb49f 100644 (file)
@@ -65,6 +65,9 @@ namespace Crow.Drawing
                public void WriteToPng (string path) {
                        NativeMethods.vkvg_surface_write_to_png (handle, path);
                }
+               public void WriteTo (IntPtr bitmap) {
+                       NativeMethods.vkvg_surface_write_to_memory (handle, bitmap);
+               }
                public void Clear () {
                        NativeMethods.vkvg_surface_clear (handle);
                }
index 6b1ce5e5aa016ce27bb1763fac35bfede77fb255..801458a2658b8b22efe2ffbc9843e3c3eef6f07c 100644 (file)
@@ -16,34 +16,29 @@ namespace Crow.Drawing {
        /// <summary>
        /// Base class for offscreen vulkan context without swapchain
        /// </summary>
-       public class VulkanContextBase : IDisposable {
+       public abstract class VulkanContextBase : IDisposable {
+               protected Interface iface;
+               public uint width { get; protected set; }
+               public uint height { get; protected set; }
+
                protected Instance instance;    
                protected PhysicalDevice phy;
                protected vke.Device dev;               
                protected Queue graphicQueue;//for vkvg, we must have at least a graphic queue
+               public Crow.Drawing.Device VkvgDevice { get; protected set; }
 
                public void WaitIdle() => dev.WaitIdle ();
 
-               public VulkanContextBase () {}          
-               public VulkanContextBase (ref byte[] pBitmap) {
-#if DEBUG
-                       instance = new Instance (Ext.I.VK_EXT_debug_utils);
-#else
-                       instance = new Instance ();
-#endif
-                       phy = instance.GetAvailablePhysicalDevice ().FirstOrDefault ();
-                       VkPhysicalDeviceFeatures enabledFeatures = default;
-                       dev = new vke.Device (phy);
-                       graphicQueue = new Queue (dev, VkQueueFlags.Graphics);
-                       dev.Activate (enabledFeatures);
-               }
+               public VulkanContextBase (Interface iface) {
+                       this.iface = iface;
+               }               
 
-               public Crow.Drawing.Device CreateVkvgDevice () => 
+
+               protected void createVkvgDevice () => VkvgDevice =
                        new Crow.Drawing.Device (instance.Handle, phy.Handle, dev.VkDev.Handle, graphicQueue.qFamIndex, SampleCount.Sample_8);
-               public virtual void CreateSurface (Device vkvgDevice, int width, int height, ref Surface surf) {
-                       surf?.Dispose ();
-                       surf = new Surface (vkvgDevice, width, height);                 
-               }
+
+               public abstract void CreateSurface (int width, int height, ref Surface surf);
+               public abstract bool render ();
 
                #region IDisposable Support
                protected bool isDisposed;
@@ -51,6 +46,8 @@ namespace Crow.Drawing {
                        if (!isDisposed) {
                                dev.WaitIdle ();
 
+                               VkvgDevice.Dispose ();
+
                                if (disposing) {
                                        dev.Dispose ();
                                        instance.Dispose ();
@@ -69,23 +66,63 @@ namespace Crow.Drawing {
                }
                #endregion
        }
-       /// <summary>
-       /// Base class to build vulkan application.
-       /// Provide default swapchain with its command pool and buffers per image and the main present queue
-       /// </summary>
-       public class VulkanContext : VulkanContextBase {
-               public override void CreateSurface (Device vkvgDevice, int width, int height, ref Surface surf) {
-                       WaitIdle();
+       //vulkan context rendering to preallocated bitmap
+       public class OffscreenVulkanContext : VulkanContextBase {
+               public IntPtr bitmap { get; private set; }
+               Surface surface;
+               /// <summary>
+               /// Preallocated Pointer to output bitmap
+               /// </summary>
+               /// <param name="pBitmap"></param>
+               public OffscreenVulkanContext (Interface iface) : base (iface) {
+#if DEBUG
+                       instance = new Instance (Ext.I.VK_EXT_debug_utils);
+#else
+                       instance = new Instance ();
+#endif
+                       phy = instance.GetAvailablePhysicalDevice ().FirstOrDefault ();
+                       VkPhysicalDeviceFeatures enabledFeatures = default;
+                       dev = new vke.Device (phy);
+                       graphicQueue = new Queue (dev, VkQueueFlags.Graphics);
+                       dev.Activate (enabledFeatures);
 
-                       blitSource?.Dispose ();
+                       createVkvgDevice ();
+               }
+               public override void CreateSurface (int width, int height, ref Surface surf) {
                        surf?.Dispose ();
-                       surf = new Surface (vkvgDevice, width, height);
-                       buildBlitCommand (surf);
+                       surface = new Surface (VkvgDevice, width, height);
+                       surf = surface;
 
-                       WaitIdle();
+                       this.width = (uint)width;
+                       this.height = (uint)height;
+
+                       if (bitmap != IntPtr.Zero)
+                               Marshal.FreeHGlobal (bitmap);
+                       bitmap = Marshal.AllocHGlobal (height * width * 4);
+                       Console.WriteLine($"vkCtx.CreateOffscreenSurface: w:{width} h:{height}");
                }
+               public override bool render () {
+                       surface.WriteTo (bitmap);
+                       Console.WriteLine($"vkCtx.Render(WriteTo): w:{width} h:{height}");
+                       return true;
+               }
+               protected override void Dispose (bool disposing) {
+                       if (!isDisposed) {
+                               dev.WaitIdle ();
+
+                               surface?.Dispose ();
+                               if (bitmap != IntPtr.Zero)
+                                       Marshal.FreeHGlobal (bitmap);
 
-               uint width, height;
+                               base.Dispose (disposing);
+                       }
+               }
+       }
+       /// <summary>
+       /// Base class to build vulkan application.
+       /// Provide default swapchain with its command pool and buffers per image and the main present queue
+       /// </summary>
+       public class VulkanContext : VulkanContextBase {
                IntPtr hWin;/** GLFW window native pointer. */
                /**Vulkan Surface */
                protected VkSurfaceKHR hSurf;
@@ -104,7 +141,7 @@ namespace Crow.Drawing {
                uint frameCount;
                Stopwatch frameChrono;
 
-               public VulkanContext (IntPtr hWin, uint _width, uint _height, bool vsync = false) {
+               public VulkanContext (Interface iface, IntPtr hWin, uint _width, uint _height, bool vsync = false) : base (iface) {
                        this.hWin = hWin;
 
                        SwapChain.IMAGES_USAGE = VkImageUsageFlags.ColorAttachment | VkImageUsageFlags.TransferDst;
@@ -150,9 +187,21 @@ namespace Crow.Drawing {
                                drawComplete[i].SetDebugMarkerName (dev, "Semaphore DrawComplete" + i);
                        }
 
-                       cmdPool.SetName ("main CmdPool");                       
+                       cmdPool.SetName ("main CmdPool");
+
+                       createVkvgDevice ();
                }
 
+               public override void CreateSurface (int width, int height, ref Surface surf) {
+                       WaitIdle();
+
+                       blitSource?.Dispose ();
+                       surf?.Dispose ();
+                       surf = new Surface (VkvgDevice, width, height);
+                       buildBlitCommand (surf);
+
+                       WaitIdle();
+               }
 
                internal vke.Image blitSource;
                
@@ -190,15 +239,11 @@ namespace Crow.Drawing {
                                cmd.End ();
                        }
                }
-               public void WaitAndResetDrawFence () {
-                       drawFence.Wait ();
-                       drawFence.Reset ();
-               }
                /// <summary>
                /// Main render method called each frame. get next swapchain image, process resize if needed, submit and present to the presentQueue.
                /// Wait QueueIdle after presenting.
                /// </summary>
-               public bool render () {
+               public override bool render () {
                        WaitIdle();
 
                        int idx = swapChain.GetNextImage ();
@@ -211,12 +256,15 @@ namespace Crow.Drawing {
 
                        if (cmds[idx] == null)
                                return false;
-                       WaitAndResetDrawFence();
+
+                       drawFence.Wait ();
+                       drawFence.Reset ();
 
                        graphicQueue.Submit (cmds[idx], swapChain.presentComplete, drawComplete[idx], drawFence);
                        (graphicQueue as PresentQueue).Present (swapChain, drawComplete[idx]);
 
                        WaitIdle();
+                       iface.IsDirty = false;
                        return true;
                }
                protected override void Dispose (bool disposing) {
index 21191f08052e76c9be329e87ad7d1f2b949ea3ee..8725a27bdc07894b8abf45071e7401f57d861f05 100644 (file)
@@ -187,13 +187,27 @@ namespace Crow
                        Glfw3.SetCursorPosCallback (hWin, HandleCursorPosDelegate);
                        Glfw3.SetScrollCallback (hWin, HandleScrollDelegate);
                        Glfw3.SetCharCallback (hWin, HandleCharDelegate);
+#if !VKVG//resize is processed on context.Render failing
                        Glfw3.SetWindowSizeCallback (hWin, HandleWindowSizeDelegate);
+#endif
                        Glfw3.SetWindowRefreshCallback (hWin, HandleWindowRefreshDelegate);
                }
 #if VKVG
-               VulkanContext vkCtx;
-               internal Device vkvgDevice;
+               protected VulkanContextBase vkCtx;
+               internal Device vkvgDevice => vkCtx.VkvgDevice;
+
+               /// <summary>
+               /// Create the VulkanContext with swapchain support. Override it to use another vulkan backend.
+               /// </summary>
 #endif
+               protected void initBackend (bool offscreen = false) {
+#if VKVG
+                       if (offscreen)
+                               vkCtx = new OffscreenVulkanContext (this);
+                       else
+                               vkCtx = new VulkanContext (this, hWin, (uint)clientRectangle.Width, (uint)clientRectangle.Height);
+#endif
+               }
                protected void initSurface ()
                {
                        Glfw3.Init ();
@@ -210,9 +224,8 @@ namespace Crow
                        registerGlfwCallbacks ();
 
 #if VKVG
-                       vkCtx = new VulkanContext (hWin, (uint)clientRectangle.Width, (uint)clientRectangle.Height);
-                       vkvgDevice = vkCtx.CreateVkvgDevice ();
-                       vkCtx.CreateSurface (vkvgDevice, clientRectangle.Width, clientRectangle.Height, ref surf);                      
+                       initBackend ();
+                       vkCtx.CreateSurface (clientRectangle.Width, clientRectangle.Height, ref surf);
 #else
                        switch (Environment.OSVersion.Platform) {
                        case PlatformID.MacOSX:
@@ -237,7 +250,52 @@ namespace Crow
                        }
 #endif
                }
-
+               public void CreateMainSurface (ref Rectangle r) {
+                       surf?.Dispose();
+#if (VKVG)
+                       vkCtx.CreateSurface (clientRectangle.Width, clientRectangle.Height, ref surf);
+#else
+                       surf = new ImageSurface (Format.Argb32, r.Width, r.Height);
+#endif
+               }               
+               public Surface CreateSurface (ref Rectangle r) {
+#if (VKVG)
+                       return new Surface (vkvgDevice, r.Width, r.Height);
+#else
+                       return surf.CreateSimilar (Content.ColorAlpha, r.Width, r.Height);
+#endif
+               }
+               public Surface CreateSurface (int width, int height) {
+#if (VKVG)
+                       return new Surface (vkvgDevice, width, height);
+#else
+                       return surf.CreateSimilar (Content.ColorAlpha, width, height);
+#endif     
+               }
+               public Surface CreateSurface (IntPtr existingSurfaceHandle) {
+#if (VKVG)
+                       return new Surface (vkvgDevice, existingSurfaceHandle);
+#else
+                       return Surface.Lookup (existingSurfaceHandle, false);                        
+#endif
+               }
+               public Surface CreateSurfaceForData (IntPtr data, int width, int height) {
+#if (VKVG)
+                       throw new NotImplementedException ();
+#else
+                       return new ImageSurface (data, Format.Argb32, width, height, width * 4);
+#endif
+               }
+               public IntPtr SurfacePointer {
+                       get {
+                               lock(UpdateMutex)
+#if (VKVG)
+                                       return (vkCtx as OffscreenVulkanContext).bitmap;
+#else
+                                       return surf.Handle;
+#endif
+                       }
+               }
                public void SetWindowIcon (string path) {
                        using (Stream stream = GetStreamFromPath (path)) {
 #if STB_SHARP
@@ -329,27 +387,7 @@ namespace Crow
                };
 
                #endregion
-               public Surface CreateSurface (ref Rectangle r) {
-#if (VKVG)
-                       return new Surface (vkvgDevice, r.Width, r.Height);
-#else
-                       return surf.CreateSimilar (Content.ColorAlpha, r.Width, r.Height);
-#endif                  
-               }
-               public Surface CreateSurface (int width, int height) {
-#if (VKVG)
-                       return new Surface (vkvgDevice, width, height);
-#else
-                       return surf.CreateSimilar (Content.ColorAlpha, width, height);
-#endif                  
-               }
-               public Surface CreateSurface (IntPtr existingSurfaceHandle) {
-#if (VKVG)
-                       return new Surface (vkvgDevice, existingSurfaceHandle);
-#else
-                       return Surface.Lookup (existingSurfaceHandle, false);                        
-#endif                  
-                               }
+               
                public string WindowTitle {                     
                        set => Glfw3.SetWindowTitle (hWin, value);
                }
@@ -449,6 +487,9 @@ namespace Crow
                                if (disposing)
                                {
                                        // TODO: dispose managed state (managed objects).
+#if VKVG
+                                       vkCtx.Dispose ();
+#endif
                                }
 
                                currentCursor?.Dispose ();
@@ -1080,11 +1121,8 @@ namespace Crow
 
 #if VKVG
                                if (IsDirty) {
-                                       if (vkCtx.render ())
-                                               IsDirty = false;
-                                       else {
-                                               resizeVulkanContext();
-                                       }
+                                       if (!vkCtx.render ())
+                                               ProcessResize (new Rectangle (0,0,(int)vkCtx.width, (int)vkCtx.height));
                                }
 #endif                 
                                
@@ -1100,13 +1138,9 @@ namespace Crow
                }
 #if VKVG
                void resizeVulkanContext () {
+                       
 
-                       vkCtx.CreateSurface (vkvgDevice, clientRectangle.Width, clientRectangle.Height, ref surf);
-
-                       foreach (Widget g in GraphicTree)
-                               g.RegisterForLayouting (LayoutingType.All);
 
-                       registerRefreshClientRectangle ();
                }
 #endif
                /// <summary>Layouting loop, this is the first step of the udpate and process registered
@@ -1436,11 +1470,12 @@ namespace Crow
                /// when window resize event occurs. 
                /// </summary>
                /// <param name="bounds">bounding box of the interface</param>
-               public virtual void ProcessResize(Rectangle bounds){                    
+               public virtual void ProcessResize(Rectangle bounds){
                        lock (UpdateMutex) {
                                clientRectangle = bounds;
 
 #if VKVG
+                               vkCtx.CreateSurface (clientRectangle.Width, clientRectangle.Height, ref surf);
 #else
                                switch (Environment.OSVersion.Platform) {
                                case PlatformID.MacOSX:
@@ -1463,11 +1498,11 @@ namespace Crow
                                case PlatformID.WinCE:
                                        throw new PlatformNotSupportedException ("Unable to create cairo surface.");
                                }
+#endif
                                foreach (Widget g in GraphicTree)
                                        g.RegisterForLayouting (LayoutingType.All);
 
                                registerRefreshClientRectangle ();
-#endif
                        }
                }
 
index 54413ba68fda75610ccc2cbb16c0df946cb1f9ec..8259275b96d1316fcbeb900a82ca577b90b01476 100644 (file)
@@ -11,8 +11,5 @@
                        <LogicalName>Dbg.%(Filename)%(Extension)</LogicalName>
                </EmbeddedResource>     
        </ItemGroup>
-       <ItemGroup>
-               <ProjectReference Include="..\..\CrowDbgShared\CrowDbgShared.csproj" />
-       </ItemGroup>
 
 </Project>
\ No newline at end of file
index 08927566e092c77afb1d1ce6f68355008b169759..40656bfe50acf0315e22c52ca5caba9438b6f648 100644 (file)
@@ -6,6 +6,7 @@ using System;
 using Crow.Drawing;
 using System.Threading;
 using Samples;
+using System.Runtime.InteropServices;
 
 namespace Crow
 {
@@ -18,7 +19,11 @@ namespace Crow
                public DebugInterface (IntPtr hWin) : base (hWin)
                {
                        SolidBackground = false;
-                       surf = CreateSurface (100, 100);
+                       initBackend (true);
+                       
+                       clientRectangle = new Rectangle (0, 0, 100, 100);
+                       CreateMainSurface (ref clientRectangle);
+
                }
 
                public override void Run()
@@ -30,14 +35,14 @@ namespace Crow
                        };
                        t.Start ();
                }
-               public bool Terminate;
+               public bool ShutDown;
                string source;
                Action delRegisterForRepaint;//call RegisterForRepaint in the container widget (DebugInterfaceWidget)
                Action<Exception> delSetCurrentException;
                Func<object> delGetScreenCoordinate;
 
                void interfaceThread () {
-                       while (!Terminate) {
+                       while (!ShutDown) {
                                try
                                {
                                        Update();       
@@ -70,20 +75,12 @@ namespace Crow
                                        Thread.Sleep(1000);     
                                }
                                
-                               if (IsDirty) {
+                               if (IsDirty) 
                                        delRegisterForRepaint();
-                                       //Console.WriteLine ("[DbgIFace]RegisterForRepaint");
-                               }
-                                       
+
                                Thread.Sleep (UPDATE_INTERVAL);
                        }
                }
-               public IntPtr SurfacePointer {
-                       get {
-                               lock(UpdateMutex)
-                                       return surf.Handle;
-                       }
-               }
                public void RegisterDebugInterfaceCallback (object w){
                        Type t = w.GetType();
                        delRegisterForRepaint = (Action)Delegate.CreateDelegate(typeof(Action), w, t.GetMethod("RegisterForRepaint"));
@@ -121,13 +118,18 @@ namespace Crow
                        }
                }
                public void Resize (int width, int height) {
-                       
+                       if (!HaveVkvgBackend)
+                               ProcessResize (new Rectangle(0,0,width, height));
+               }
+               public override void ProcessResize(Rectangle bounds) {
                        lock (UpdateMutex) {
-                               clientRectangle = new Rectangle (0, 0, width, height);
-                               surf?.Dispose();
-                               surf = CreateSurface (width, height);                           
+                               clientRectangle = bounds.Size;
+                               
+                               CreateMainSurface (ref clientRectangle);
+
                                foreach (Widget g in GraphicTree)
                                        g.RegisterForLayouting (LayoutingType.All);
+
                                RegisterClip (clientRectangle);
                        }                               
                }
index 8da93de040028c723b1c60db28dfee085f1213b0..113e5e0731a1d873a4f74245455c167d008f4860 100644 (file)
@@ -34,12 +34,12 @@ namespace Crow
                Action delResetDirtyState;
                Action delResetDebugger;
                Action<object, string> delSaveDebugLog;         
-               Func<IntPtr> delGetSurfacePointer;
+               Func<IntPtr> delGetSurfacePointer;              
                Action<string> delSetSource;
 
                FieldInfo fiDbg_IncludeEvents, fiDbg_DiscardEvents, fiDbg_ConsoleOutput;
                
-               bool initialized, recording;
+               bool initialized, recording, hasVkvgBackend;
                string crowDbgAssemblyLocation;
                DbgEvtType recordedEvents, discardedEvents;
 
@@ -198,6 +198,11 @@ namespace Crow
                        }
                        
                        crowLoadCtx = new AssemblyLoadContext("CrowDebuggerLoadContext");
+                       crowLoadCtx.Resolving += (context, assemblyName) => {
+                               return crowLoadCtx.LoadFromAssemblyPath (
+                                       System.IO.Path.Combine (
+                                               System.IO.Path.GetDirectoryName(crowDbgAssemblyLocation), assemblyName.Name + ".dll"));
+                       };
                
                        //using (crowLoadCtx.EnterContextualReflection()) {
                                crowAssembly = crowLoadCtx.LoadFromAssemblyPath (crowDbgAssemblyLocation);
@@ -210,7 +215,6 @@ namespace Crow
                                }                               
 
                                dbgIfaceType = thisAssembly.GetType("Crow.DebugInterface");
-                               
                                dbgIFace = Activator.CreateInstance (dbgIfaceType, new object[] {IFace.WindowHandle});
 
                                delResize = (Action<int, int>)Delegate.CreateDelegate(typeof(Action<int, int>),
@@ -252,6 +256,7 @@ namespace Crow
                                                                                        null, debuggerType.GetMethod("Reset"));
                                /*delSaveDebugLog = (Action<object, string>)Delegate.CreateDelegate(typeof(Action<object, string>),
                                                                                        null, debuggerType.GetMethod("Save", new Type[] {dbgIfaceType, typeof(string)}));*/
+                               hasVkvgBackend = (bool)dbgIfaceType.GetField ("HaveVkvgBackend", BindingFlags.Public | BindingFlags.Static | BindingFlags.FlattenHierarchy).GetValue (null);
 
                                dbgIfaceType.GetMethod("RegisterDebugInterfaceCallback").Invoke (dbgIFace, new object[] {this} );                               
                                dbgIfaceType.GetMethod("Run").Invoke (dbgIFace, null);
@@ -265,7 +270,6 @@ namespace Crow
 
                protected override void onDraw(Context gr)
                {
-                       Console.WriteLine("onDraw");
                        gr.SetSource(Colors.RoyalBlue);
                        gr.Paint();
                }
@@ -376,8 +380,12 @@ namespace Crow
                        bmp?.Dispose ();                
                        
                        if (initialized) {
-                               delResize (Slot.Width, Slot.Height);                    
-                               bmp = IFace.CreateSurface (delGetSurfacePointer());
+                               delResize (Slot.Width, Slot.Height);
+                               if (hasVkvgBackend)             
+                                       bmp = IFace.CreateSurfaceForData (delGetSurfacePointer(), Slot.Width, Slot.Height);
+                               else
+                                       bmp = IFace.CreateSurface (delGetSurfacePointer());
+                                       
                        } else
                                bmp = IFace.CreateSurface (Slot.Width, Slot.Height);