mirror of
https://github.com/pkdawson/imgui-godot.git
synced 2026-09-19 05:04:17 +00:00
clean up new renderer, prepare for beta 5
This commit is contained in:
@@ -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
|
||||
}
|
||||
|
||||
@@ -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)
|
||||
{
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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();
|
||||
|
||||
@@ -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
|
||||
@@ -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"
|
||||
|
||||
Reference in New Issue
Block a user