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);
}
/// <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;
if (!isDisposed) {
dev.WaitIdle ();
+ VkvgDevice.Dispose ();
+
if (disposing) {
dev.Dispose ();
instance.Dispose ();
}
#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;
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;
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;
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 ();
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) {
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 ();
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:
}
#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
};
#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);
}
if (disposing)
{
// TODO: dispose managed state (managed objects).
+#if VKVG
+ vkCtx.Dispose ();
+#endif
}
currentCursor?.Dispose ();
#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
}
#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
/// 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:
case PlatformID.WinCE:
throw new PlatformNotSupportedException ("Unable to create cairo surface.");
}
+#endif
foreach (Widget g in GraphicTree)
g.RegisterForLayouting (LayoutingType.All);
registerRefreshClientRectangle ();
-#endif
}
}
<LogicalName>Dbg.%(Filename)%(Extension)</LogicalName>
</EmbeddedResource>
</ItemGroup>
- <ItemGroup>
- <ProjectReference Include="..\..\CrowDbgShared\CrowDbgShared.csproj" />
- </ItemGroup>
</Project>
\ No newline at end of file
using Crow.Drawing;
using System.Threading;
using Samples;
+using System.Runtime.InteropServices;
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()
};
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();
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"));
}
}
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);
}
}
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;
}
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);
}
dbgIfaceType = thisAssembly.GetType("Crow.DebugInterface");
-
dbgIFace = Activator.CreateInstance (dbgIfaceType, new object[] {IFace.WindowHandle});
delResize = (Action<int, int>)Delegate.CreateDelegate(typeof(Action<int, int>),
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);
protected override void onDraw(Context gr)
{
- Console.WriteLine("onDraw");
gr.SetSource(Colors.RoyalBlue);
gr.Paint();
}
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);