clean up new renderer, prepare for beta 5

This commit is contained in:
Patrick Dawson
2022-11-11 21:46:32 +01:00
parent 513ce4b02e
commit d685cb4992
6 changed files with 79 additions and 36 deletions

View File

@@ -63,11 +63,11 @@ public static class ImGuiGD
{
}
public static void Init(float? scale = null)
public static void Init(float? scale = null, Renderer renderer = Renderer.RenderingDevice)
{
if (IntPtr.Size != sizeof(ulong))
{
GD.PrintErr("imgui-godot requires 64-bit pointers");
throw new PlatformNotSupportedException("imgui-godot requires 64-bit pointers");
}
if (scale != null)
@@ -75,7 +75,12 @@ public static class ImGuiGD
_scale = scale.Value;
}
Internal.Init();
Internal.Init(renderer switch
{
Renderer.Canvas => new InternalCanvasRenderer(),
Renderer.RenderingDevice => new InternalRdRenderer(),
_ => throw new ArgumentException("Invalid renderer", nameof(renderer))
});
}
public static void ResetFonts()
@@ -179,3 +184,9 @@ public static class ImGuiGD
Internal.SetIniFilename(io, fileName);
}
}
public enum Renderer
{
Canvas,
RenderingDevice
}

View File

@@ -29,6 +29,9 @@ public partial class ImGuiLayer : CanvasLayer
/// </summary>
[Signal] public delegate void ImGuiLayoutEventHandler();
[Export(PropertyHint.Enum, "RenderingDevice,Canvas")]
public string Renderer = "RenderingDevice";
private Window _window;
private SubViewportContainer _subViewportContainer;
private SubViewport _subViewport;
@@ -56,7 +59,7 @@ public partial class ImGuiLayer : CanvasLayer
VisibilityChanged += OnChangeVisibility;
ImGuiGD.ScaleToDpi = ScaleToDpi;
ImGuiGD.Init(Scale);
ImGuiGD.Init(Scale, Enum.Parse<Renderer>(Renderer));
ImGui.GetIO().SetIniFilename(IniFilename);
if (Font is not null)
{

View File

@@ -11,6 +11,7 @@ namespace ImGuiGodot;
internal interface IRenderer
{
public string Name { get; }
public void InitViewport(Viewport vp);
public void CloseViewport(Viewport vp);
public void RenderDrawData(Viewport vp, ImDrawDataPtr drawData);
@@ -27,8 +28,9 @@ internal static class Internal
private static Vector2 _mouseWheel = Vector2.Zero;
private static ImGuiMouseCursor _currentCursor = ImGuiMouseCursor.None;
private static readonly IntPtr _backendName = Marshal.StringToCoTaskMemAnsi("imgui_impl_godot4_net");
private static IntPtr _rendererName = IntPtr.Zero;
private static IntPtr _iniFilenameBuffer = IntPtr.Zero;
internal static IRenderer Renderer { get; }
internal static IRenderer Renderer { get; private set; }
private class FontParams
{
@@ -46,7 +48,7 @@ internal static class Internal
if (cinfo is null)
{
GD.PrintErr("failed to get RID constructor");
return;
throw new PlatformNotSupportedException();
}
DynamicMethod dm = new("ConstructRID", typeof(RID), new[] { typeof(ulong) });
@@ -55,17 +57,11 @@ internal static class Internal
il.Emit(OpCodes.Newobj, cinfo);
il.Emit(OpCodes.Ret);
ConstructRID = dm.CreateDelegate<Func<ulong, RID>>();
#if IMGUI_GODOT_DEV
Renderer = new InternalVkRenderer();
#else
Renderer = new InternalCanvasRenderer();
#endif
}
public static void AddFont(FontFile fontData, float fontSize, bool merge)
public static void AddFont(FontFile fontData, int fontSize, bool merge)
{
_fontConfiguration.Add(new FontParams { Font = fontData, FontSize = (int)fontSize, Merge = merge });
_fontConfiguration.Add(new FontParams { Font = fontData, FontSize = fontSize, Merge = merge });
}
private static unsafe void _AddFont(FontFile fontData, int fontSize, bool merge)
@@ -196,8 +192,9 @@ internal static class Internal
ImGui.GetStyle().ScaleAllSizes(scale);
}
public static void Init()
public static void Init(IRenderer renderer)
{
Renderer = renderer;
_fontConfiguration.Clear();
if (ImGui.GetCurrentContext() != IntPtr.Zero)
@@ -215,10 +212,15 @@ internal static class Internal
io.BackendFlags |= ImGuiBackendFlags.HasMouseCursors;
io.BackendFlags |= ImGuiBackendFlags.RendererHasVtxOffset;
if (_rendererName == IntPtr.Zero)
{
_rendererName = Marshal.StringToCoTaskMemAnsi(Renderer.Name);
}
unsafe
{
io.NativePtr->BackendPlatformName = (byte*)_backendName;
io.NativePtr->BackendRendererName = (byte*)_backendName;
io.NativePtr->BackendRendererName = (byte*)_rendererName;
}
#if IMGUI_GODOT_DEV

View File

@@ -16,6 +16,8 @@ internal class InternalCanvasRenderer : IRenderer
private readonly Dictionary<RID, List<RID>> _canvasItemPools = new();
private readonly Dictionary<RID, ViewportData> _vpData = new();
public string Name => "imgui_impl_godot4_canvas";
public void InitViewport(Viewport vp)
{
RID vprid = vp.GetViewportRid();

View File

@@ -1,4 +1,3 @@
#if IMGUI_GODOT_DEV
using Godot;
using ImGuiNET;
using System;
@@ -7,27 +6,34 @@ using System.Runtime.InteropServices;
namespace ImGuiGodot;
internal class InternalVkRenderer : IRenderer
internal class InternalRdRenderer : IRenderer
{
private readonly RenderingDevice RD;
private readonly Color[] clearColors = new[] { new Color(0f, 0f, 0f, 0f) };
//private readonly Color[] clearColors = new[] { new Color(0.45098f, 0.54902f, 0.60f) };
private readonly RID _shader;
private readonly RID _pipeline;
private readonly RID _sampler;
private readonly long _vtxFormat;
private readonly Dictionary<RID, RID> _framebuffers = new();
public InternalVkRenderer()
public string Name => "imgui_impl_godot4_rd";
public InternalRdRenderer()
{
RD = RenderingServer.GetRenderingDevice();
var src = new RDShaderSource();
src.SourceVertex = vertexShaderSource;
src.SourceFragment = fragmentShaderSource;
// set up everything to match the official Vulkan backend as closely as possible
// compile shader
var src = new RDShaderSource
{
SourceVertex = vertexShaderSource,
SourceFragment = fragmentShaderSource
};
var spirv = RD.ShaderCompileSpirvFromSource(src);
_shader = RD.ShaderCreateFromSpirv(spirv);
// create vertex format
uint vtxStride = (uint)Marshal.SizeOf<ImDrawVert>();
RDVertexAttribute attrPoints = new()
@@ -57,6 +63,7 @@ internal class InternalVkRenderer : IRenderer
var vattrs = new Godot.Collections.Array<RDVertexAttribute>() { attrPoints, attrUvs, attrColors };
_vtxFormat = RD.VertexFormatCreate(vattrs);
// blend state
var bsa = new RDPipelineColorBlendStateAttachment
{
EnableBlend = true,
@@ -69,15 +76,20 @@ internal class InternalVkRenderer : IRenderer
DstAlphaBlendFactor = RenderingDevice.BlendFactor.OneMinusSrcAlpha,
AlphaBlendOp = RenderingDevice.BlendOperation.Add,
};
var blendData = new RDPipelineColorBlendState();
blendData.Attachments.Add(bsa);
blendData.BlendConstant = new Color(0, 0, 0, 0);
var blendData = new RDPipelineColorBlendState
{
BlendConstant = new Color(0, 0, 0, 0),
};
blendData.Attachments.Add(bsa);
// rasterization state
var rasterizationState = new RDPipelineRasterizationState
{
FrontFace = RenderingDevice.PolygonFrontFace.CounterClockwise
};
// pipeline
_pipeline = RD.RenderPipelineCreate(
_shader,
RD.ScreenGetFramebufferFormat(),
@@ -88,6 +100,7 @@ internal class InternalVkRenderer : IRenderer
new RDPipelineDepthStencilState(),
blendData);
// sampler used for all textures
var samplerState = new RDSamplerState
{
MinFilter = RenderingDevice.SamplerFilter.Linear,
@@ -133,7 +146,7 @@ internal class InternalVkRenderer : IRenderer
Buffer.BlockCopy(translate, 0, pcbuf, 8, 8);
var vtxBuffers = new RID[drawData.CmdListsCount];
var vtxArrays = new RID[drawData.CmdListsCount];
var vtxArrays = new List<Dictionary<uint, RID>>(drawData.CmdListsCount);
var idxBuffers = new RID[drawData.CmdListsCount];
var idxArrays = new List<RID[]>(drawData.CmdListsCount);
var uniformSets = new Dictionary<IntPtr, RID>();
@@ -151,8 +164,7 @@ internal class InternalVkRenderer : IRenderer
Marshal.Copy(cmdList.IdxBuffer.Data, idxBuf, 0, idxBytes);
vtxBuffers[i] = RD.VertexBufferCreate((uint)vertBuf.Length, vertBuf);
vtxArrays[i] = RD.VertexArrayCreate((uint)cmdList.VtxBuffer.Size, _vtxFormat,
new() { vtxBuffers[i], vtxBuffers[i], vtxBuffers[i] });
vtxArrays.Add(new());
idxBuffers[i] = RD.IndexBufferCreate((uint)cmdList.IdxBuffer.Size, RenderingDevice.IndexBufferFormat.Uint16, idxBuf);
@@ -161,11 +173,23 @@ internal class InternalVkRenderer : IRenderer
for (int cmdi = 0; cmdi < cmdList.CmdBuffer.Size; ++cmdi)
{
ImDrawCmdPtr drawCmd = cmdList.CmdBuffer[cmdi];
if (drawCmd.ElemCount == 0)
continue;
idxArrays[i][cmdi] = RD.IndexArrayCreate(idxBuffers[i], drawCmd.IdxOffset, drawCmd.ElemCount);
if (drawCmd.VtxOffset > 0)
if (!vtxArrays[i].ContainsKey(drawCmd.VtxOffset))
{
// TODO: ...
long voff = drawCmd.VtxOffset * vertSize;
#if IMGUI_GODOT_DEV
vtxArrays[i][drawCmd.VtxOffset] = RD.VertexArrayCreate((uint)cmdList.VtxBuffer.Size, _vtxFormat,
new() { vtxBuffers[i], vtxBuffers[i], vtxBuffers[i] },
new[] { voff, voff, voff });
#else
// TODO: offsets workaround
vtxArrays[i][drawCmd.VtxOffset] = RD.VertexArrayCreate((uint)cmdList.VtxBuffer.Size, _vtxFormat,
new() { vtxBuffers[i], vtxBuffers[i], vtxBuffers[i] });
#endif
}
IntPtr texid = drawCmd.GetTexID();
@@ -195,8 +219,6 @@ internal class InternalVkRenderer : IRenderer
{
ImDrawListPtr cmdList = drawData.CmdListsRange[i];
RD.DrawListBindVertexArray(dl, vtxArrays[i]);
for (int cmdi = 0; cmdi < cmdList.CmdBuffer.Size; ++cmdi)
{
ImDrawCmdPtr drawCmd = cmdList.CmdBuffer[cmdi];
@@ -206,6 +228,7 @@ internal class InternalVkRenderer : IRenderer
RD.DrawListBindUniformSet(dl, uniformSets[drawCmd.GetTexID()], 0);
RD.DrawListBindIndexArray(dl, idxArrays[i][cmdi]);
RD.DrawListBindVertexArray(dl, vtxArrays[i][drawCmd.VtxOffset]);
RD.DrawListEnableScissor(dl, new Rect2(
drawCmd.ClipRect.X,
@@ -218,7 +241,10 @@ internal class InternalVkRenderer : IRenderer
RD.FreeRid(idxArrays[i][cmdi]);
}
RD.FreeRid(vtxArrays[i]);
foreach (RID rid in vtxArrays[i].Values)
{
RD.FreeRid(rid);
}
RD.FreeRid(vtxBuffers[i]);
RD.FreeRid(idxBuffers[i]);
}
@@ -277,4 +303,3 @@ void main()
fColor = In.Color * texture(sTexture, In.UV.st);
}";
}
#endif

View File

@@ -3,5 +3,5 @@
name="Dear ImGui for Godot"
description="Dear ImGui for Godot"
author="Patrick Dawson"
version="3.2.0"
version="3.3.0"
script="ImGuiPlugin.gd"