JingboYang / slimdx

Automatically exported from code.google.com/p/slimdx
MIT License
0 stars 0 forks source link

Fix for UVAtlas callbacks does not work #849

Closed GoogleCodeExporter closed 9 years ago

GoogleCodeExporter commented 9 years ago
I get:

ArgumentException: The specified Type must not be a generic type definition.
Parameter name: delegate

from Marshal::GetFunctionPointerForDelegate

Which seems like a rather odd error message(with .NET framework 4). 

IIRC I fixed this before by just converting the GCHandle to a pointer, no call 
to Marshal::GetFunctionPointerForDelegate(callback);

Original issue reported on code.google.com by dbl...@fastmail.fm on 20 Nov 2011 at 1:38

GoogleCodeExporter commented 9 years ago
So this is in reference to issue 837. From what I can see, .NET has some kind 
of problem doing the Marshal when the target is a generic, even a fully 
resolved generic. At least that's what it says in this thread:
http://www.gamedev.net/topic/490114-generic-delegates-and-getdelegateforfunction
pointer/
Which is, in a stroke of irony, explained by MikeP.

If I understand correctly, your fix basically just pins the delegate and passes 
the result directly as a function pointer. I don't think that's kosher, even if 
it happens to work so far. The easiest thing to do here may be to just switch 
to a custom non-generic delegate type for the call.

Original comment by promit....@gmail.com on 25 Dec 2011 at 3:41

GoogleCodeExporter commented 9 years ago
What I do is exactly the same as the Ms code for gcroot<>. I create a 
gchandle(no pinning) get the pointer, pass to uvatlass, which passes it to a 
slimdx callback,this gets the handle and obj, casts and calls as normal. 

A delegate can be treated as a. Net object and used with gcroot<> is all I am 
assuming.

Original comment by dbl...@fastmail.fm on 25 Dec 2011 at 12:20

GoogleCodeExporter commented 9 years ago
I'm also kind of skeptical that you can treat a pinned delegate as a function 
pointer. I'll do some more research and figure out the best solution for this 
situation.

Original comment by Mike.Popoloski on 30 Dec 2011 at 3:46

GoogleCodeExporter commented 9 years ago
Milestone.

Original comment by Mike.Popoloski on 30 Dec 2011 at 3:47

GoogleCodeExporter commented 9 years ago
I am not treating a pinned delegate as a function pointer!

Original comment by dbl...@fastmail.fm on 30 Dec 2011 at 12:02

GoogleCodeExporter commented 9 years ago
Maybe you can upload your patch then, because I'm not following your 
explanation.

Original comment by Mike.Popoloski on 30 Dec 2011 at 3:44

GoogleCodeExporter commented 9 years ago
Index: D:/projects/slimdx/source/direct3d9/UVAtlas.cpp
===================================================================
--- D:/projects/slimdx/source/direct3d9/UVAtlas.cpp (revision 2154)
+++ D:/projects/slimdx/source/direct3d9/UVAtlas.cpp (working copy)
@@ -106,7 +106,7 @@
            GCHandle handle = GCHandle::Alloc(callback);

            hr = D3DXUVAtlasCreate( mesh->InternalPointer, maxChartCount, maxStretch, width, height, gutter, textureIndex,
-               inputAdjacencyPtr, falseEdgesPtr, imtPtr, NativeAtlasCallback, 
callbackFrequency, 
Marshal::GetFunctionPointerForDelegate(callback).ToPointer(), 
+               inputAdjacencyPtr, falseEdgesPtr, imtPtr, NativeAtlasCallback, 
callbackFrequency, GCHandle::ToIntPtr(handle).ToPointer(), 
                static_cast<DWORD>( quality ), &meshOut, &facePartitioning, &vertexRemap, &maxStretchOut, &numChartsOut );

            handle.Free();
@@ -177,7 +177,7 @@
            GCHandle handle = GCHandle::Alloc(callback);

            hr = D3DXUVAtlasPartition( mesh->InternalPointer, maxChartCount, maxStretch, textureIndex,
-               inputAdjacencyPtr, falseEdgesPtr, imtPtr, NativeAtlasCallback, 
callbackFrequency, 
Marshal::GetFunctionPointerForDelegate(callback).ToPointer(), 
+               inputAdjacencyPtr, falseEdgesPtr, imtPtr, NativeAtlasCallback, 
callbackFrequency, GCHandle::ToIntPtr(handle).ToPointer(), 
                static_cast<DWORD>( quality ), &meshOut, &facePartitioning, &vertexRemap, &partitionResult, &maxStretchOut, &numChartsOut );

            handle.Free();
@@ -217,7 +217,7 @@
            GCHandle handle = GCHandle::Alloc(callback);

            hr = D3DXUVAtlasPack( mesh->InternalPointer, width, height, gutter, textureIndex,
-               reinterpret_cast<DWORD*>( pinnedAdj ), NativeAtlasCallback, 
callbackFrequency, 
Marshal::GetFunctionPointerForDelegate(callback).ToPointer(), 
+               reinterpret_cast<DWORD*>( pinnedAdj ), NativeAtlasCallback, 
callbackFrequency, GCHandle::ToIntPtr(handle).ToPointer(), 
                static_cast<DWORD>( quality ), facePartitioning->GetD3DBuffer() );

            handle.Free();

Original comment by dbl...@fastmail.fm on 30 Dec 2011 at 4:06

GoogleCodeExporter commented 9 years ago
Note:

* the lack of pinning in the GCHandle::Alloc() call (this is ok, since it 
doesnt matter if the delegate is moved around, the pointer we get seems to be 
the actual handle value, look to gcroot<> to show this is OK).

* The callback called by native code is "NativeAtlasCallback", which should 
actually be managed code called through a stub... This code then retrieves the 
GCHandle from the user param, gets the object and casts back to the delegate.

Original comment by dbl...@fastmail.fm on 30 Dec 2011 at 4:12

GoogleCodeExporter commented 9 years ago
Alright, should be fixed in r2158. It'd be helpful if you could try it out and 
make sure I didn't botch anything else.

Original comment by Mike.Popoloski on 1 Jan 2012 at 5:37