xiaoxiao921 / DearImGuiInjection

18 stars 3 forks source link

Fetal error in GC: Collecting from unknown thread #6

Open krulci opened 9 months ago

krulci commented 9 months ago

image Can you please provide some clue as of any design or implementation of DearImGuiInjection that deals with Garbage Collection or threading? We are getting this issue after running the game for a while when ImGui interface is enabled.

xiaoxiao921 commented 9 months ago

Sounds like this is needed but I don't have much time these days for this project at all so you'll have to figure it out

krulci commented 9 months ago

Sounds like this is needed but I don't have much time these days for this project at all so you'll have to figure it out

What would I need to attach? the Reloaded.Hooks object? (_swapChainPresentHook)

xiaoxiao921 commented 9 months ago

This error show up because there are managed objects getting collected from the GC outside of il2cpp regular threads, attaching the thread should fix these errors, my guess is that it is the Directx rendering thread that is not attached

krulci commented 9 months ago

This error show up because there are managed objects getting collected from the GC outside of il2cpp regular threads, attaching the thread should fix these errors, my guess is that it is the Directx rendering thread that is not attached

I am not too familiar with rendering API, but I have went over how DearImGuiInjection start the plugin. However, I do not recognize you started anything in a new thread. Even the SwapChain was creating in the same thread if I am not mistaken.

xiaoxiao921 commented 9 months ago

I don't start a thread but it hijack the rendering thread of the process

krulci commented 9 months ago

I don't start a thread but it hijack the rendering thread of the process

To be honest, I have no idea what I am doing, but I am trying the following attempt:

[DllImport("GameAssembly")]
private static extern void il2cpp_thread_attach(IntPtr domain);
[DllImport("GameAssembly")]
private static extern IntPtr il2cpp_domain_get();

public static void AttachThread()
{
    il2cpp_thread_attach(il2cpp_domain_get());
}
public unsafe bool Init()
{
    Log.Info("DX11Renderer.Init()");

    var windowHandle = Windows.User32.CreateFakeWindow();

    var desc = new SwapChainDescription()
    {
        BufferCount = 1,
        ModeDescription = new ModeDescription(500, 300, new Rational(60, 1), Format.R8G8B8A8_UNorm),
        IsWindowed = true,
        OutputHandle = windowHandle,
        SampleDescription = new SampleDescription(1, 0),
        Usage = Usage.RenderTargetOutput
    };

    Device.CreateWithSwapChain(DriverType.Hardware, DeviceCreationFlags.None, desc, out var device, out var swapChain);
    var swapChainVTable = VirtualFunctionTable.FromObject((nuint)(nint)swapChain.NativePointer, (nuint)Enum.GetNames(typeof(IDXGISwapChain)).Length);
    var swapChainPresentFunctionPtr = swapChainVTable.TableEntries[(int)IDXGISwapChain.Present].FunctionPointer;
    var swapChainResizeBuffersFunctionPtr = swapChainVTable.TableEntries[(int)IDXGISwapChain.ResizeBuffers].FunctionPointer;

    swapChain.Dispose();
    device.Dispose();

    Windows.User32.DestroyWindow(windowHandle);

    {
        _cache.Add(_swapChainPresentHookDelegate);

        _swapChainPresentHook = new(_swapChainPresentHookDelegate, swapChainPresentFunctionPtr);
        AttachThread();
        _swapChainPresentHook.Activate();
    }

    {
        _cache.Add(_swapChainResizeBuffersHookDelegate);

        _swapChainResizeBuffersHook = new(_swapChainResizeBuffersHookDelegate, swapChainResizeBuffersFunctionPtr);
        AttachThread();
        _swapChainResizeBuffersHook.Activate();
    }

    return true;
}