prime31 / Nez

Nez is a free 2D focused framework that works with MonoGame and FNA
MIT License
1.76k stars 357 forks source link

`GraphicsResource::UpdateResourceReference` no longer works with FNA #804

Closed VictorKoenders closed 1 month ago

VictorKoenders commented 1 month ago

6 months ago there was a commit on FNA that changed the WeakReference into a GCHandle: https://github.com/FNA-XNA/FNA/commit/c9f3ec7b3f94ef6a182496c4db2aad6985a68de0

This affects the following functions:

Nez calls these functions with reflection in GraphicsResource but now the function definition does not match any more.

The fix is fairly simple:

diff --git a/Nez.Portable/Graphics/Batcher/GraphicsResource.cs b/Nez.Portable/Graphics/Batcher/GraphicsResource.cs
index fa479930..74ce1027 100644
--- a/Nez.Portable/Graphics/Batcher/GraphicsResource.cs
+++ b/Nez.Portable/Graphics/Batcher/GraphicsResource.cs
@@ -24,12 +24,13 @@ namespace Nez
                if (_graphicsDevice != null)
                {
                    UpdateResourceReference(false);
+                   _selfReference?.Free();
                    _selfReference = null;
                }

                _graphicsDevice = value;

-               _selfReference = new WeakReference(this);
+               _selfReference = System.Runtime.InteropServices.GCHandle.Alloc(this, System.Runtime.InteropServices.GCHandleType.Weak);
                UpdateResourceReference(true);
            }
        }
@@ -40,7 +41,7 @@ namespace Nez
        // parameter is true. If disposing is false, the GraphicsDevice may or may not be disposed yet.
        GraphicsDevice _graphicsDevice;

-       WeakReference _selfReference;
+       System.Runtime.InteropServices.GCHandle? _selfReference;

        internal GraphicsResource()
@@ -83,6 +84,7 @@ namespace Nez
                if (GraphicsDevice != null)
                    UpdateResourceReference(false);

+               _selfReference?.Free();
                _selfReference = null;
                _graphicsDevice = null;
                IsDisposed = true;
@@ -94,7 +96,7 @@ namespace Nez
        {
            var method = shouldAdd ? "AddResourceReference" : "RemoveResourceReference";
            var methodInfo = ReflectionUtils.GetMethodInfo(GraphicsDevice, method);
-           methodInfo.Invoke(GraphicsDevice, new object[] {_selfReference});
+           methodInfo.Invoke(GraphicsDevice, new object[] { _selfReference });
        }
    }
 }
\ No newline at end of file

However I'd imagine that this will break XNA and people on older versions of FNA.

VictorKoenders commented 1 month ago

Workaround in #805: either include the FNA.Core projects, or define FNA_GCHANDLE and it will switch to the GCHandle type