galakt / slimdx

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

ngen.exe fails generating image for dll that references SlimDX #377

Closed GoogleCodeExporter closed 8 years ago

GoogleCodeExporter commented 8 years ago
My application uses the SlimDX November 2008 runtime, which I recently
switched to from Managed DX. Now, when I try to run ngen.exe on my
application, I get the following error:

Error compiling HalflingWin32, Version=1.0.0.0, Culture=neutral,
PublicKeyToken=
fb1ae2b2d44045eb: Internal CLR error. (Exception from HRESULT: 0x80131506)
Internal CLR error. (Exception from HRESULT: 0x80131506)

HalflingWin32 is a DLL that references SlimDX. More specifically, Direc3D,
DirectSound, and DirectInput.

If you don't know about ngen.exe, here's an article on MSDN:

http://msdn.microsoft.com/en-us/library/6t9t5wcf.aspx

Thanks.

Original issue reported on code.google.com by holyfuzz...@gmail.com on 7 Dec 2008 at 6:39

GoogleCodeExporter commented 8 years ago
Interesting. My hunch is that this has something to do with the 32/64 bit 
problems 
that plague us due to having native code in the assembly, but I'm not sure.

I can ngen the x86 Release MiniTri10 just fine with the command line "ngen.exe 
install MiniTri.exe" and "ngen.exe MiniTri.exe" -- niether produce errors like 
above. What command line are you using to get this error and what are your 
build 
settings (in particular, platform and configuration) for your assembly?

Original comment by josh.petrie on 8 Jan 2009 at 1:59

GoogleCodeExporter commented 8 years ago
I have attached a zip containing the ngen'ed files and a batch script that 
calls ngen
on the files.

The error happens on both WinXP and Vista (both 32 bit, have not tried 64).

The HalflingWin32 assembly is a class library targeting .Net 3.5. The platform 
I'm
targeting is "Any CPU". The error happens on both Debug and Release builds (the
attached happens to be a debug build) and happens regardless of whether 
"client-only
framework subset" is checked. The assembly contains no unmanaged code, though 
it does
contain unsafe code and calls to unmanaged DLLs.

I have also attached the csproj file for the assembly if that helps. I can also
provide the source code if that proves necessary, but I don't wish to post it 
publicly.

Thanks for all your great work. That I'm reporting such a minor problem is a
testament to the quality of this product.

Original comment by holyfuzz...@gmail.com on 8 Jan 2009 at 2:29

Attachments:

GoogleCodeExporter commented 8 years ago
Alright. Using the released Nov 2008 SDK version of SlimDX, I was able to get 
ngen 
to fail, but not with quite the same error. I put that version of SlimDX.dll 
into 
the same directory as your program and ran your ngen.bat. It failed compiling 
HalflingWin32, but with E_FAIL and not a "CLR internal error."

Some other hits on the web suggest the CLR internal error thing is related to 
strangeness with the assembly metadata. I have attached a release build of 
SlimDX.dll from the head of the SVN, can you swap that out with whatever 
SlimDX.dll 
you are currently depending on and rebuild your app with it, and see what ngen 
says 
then? I am unable to do so because the versions are different and ngen will not 
use 
the SVN trunk version.

It doesn't look like this is related to an Any CPU issue, but just in case, 
before 
or after you try the above test, toggle your platform target to x86, rebuild, 
and 
see if that changes anything.

Original comment by josh.petrie on 8 Jan 2009 at 3:08

Attachments:

GoogleCodeExporter commented 8 years ago
(are you expecting the SlimDX dll to be in the GAC?)

Original comment by josh.petrie on 8 Jan 2009 at 3:09

GoogleCodeExporter commented 8 years ago
My app currently depends on the Nov 08 release, and SlimDX is currently 
redistributed
with it using the SlimDX redist package.

Attached is HalflingWin32.dll recompiled against that SlimDX.dll you attached.
Running "ngen.exe install HalflingWin32.dll" results in the same above error 
for both
the old version and the new attached version. (I had to put that SlimDX.dll in 
the
same folder as HalflingWin32.dll, otherwise it gives a version error, as 
expected)

Same error if targeting x86.

- "(are you expecting the SlimDX dll to be in the GAC?)"

Um... I don't think so. To my knowledge I'm not doing anything that explicitly
requires SlimDX to be either in or not in the GAC. (Does the SlimDX redist put 
it in
the GAC?)

To satisfy my curiosity, I did "ngen.exe install SlimDX.dll", which seemed to 
work
fine (no errors printed). I then tried "ngen.exe install HalflingWin32.dll" 
again,
which failed as usual.

Are you using the ngen I included in my original zip? If not, what version are 
you
using? I'm using 2.0.50727.3053, which I *think* is the latest.

Thanks again.

Original comment by holyfuzz...@gmail.com on 8 Jan 2009 at 3:59

Attachments:

GoogleCodeExporter commented 8 years ago
I'm still having little success in reproducing or diagnosing this, 
unfortunately. 
Can you zip up an entire buildable archive of your project and email it to me 
at 
jpetrie at digipen dot edu? 

Original comment by josh.petrie on 9 Jan 2009 at 1:38

GoogleCodeExporter commented 8 years ago
Any progress on this before we close as no repro?

Original comment by promit....@gmail.com on 20 Jan 2009 at 10:21

GoogleCodeExporter commented 8 years ago
I just sent Josh the buildable archive. Sorry for the delay.

Most people get this error when they install my game Tanky-Tank, available at
http://www.tanky-tank.com/tanky-tank. (The installer will automatically run 
ngen;
don't blink or you'll miss the error when the cmd prompt closes.) Perhaps 
someone
else can also try to reproduce the error.

Thanks.

Original comment by holyfuzz...@gmail.com on 21 Jan 2009 at 12:22

GoogleCodeExporter commented 8 years ago
I have found some interesting results.

I still can't reproduce your original error, I'm still getting E_FAIL whenever 
I 
ngen your Win32 assembly against the Nov 08 SDK release. So I dug through your 
code 
and started gutting it. An empty assembly ngen's fine. I put back the audio and 
input stuff and it still was fine. The graphics stuff causes E_FAIL. Binary 
searching through Win32Display.cs leads me to your functions that call 
SetRenderState. The presence of SOME of the SetRenderState calls causes the 
E_FAIL 
error from ngen. Others seem to be okay. In particular, any calls that would 
end up 
going to the generic version of SetRenderState seems to make ngen puke. 

I cannot reproduce ANY error with SlimDX built from the SVN head. I'm syncing 
back 
to the Nov 08 tag now to see if a binary built from source there will exhibit 
the 
same behavior, to rule out possible signing issues.

Original comment by josh.petrie on 23 Jan 2009 at 5:10

GoogleCodeExporter commented 8 years ago
Alright. I've managed to get the error to go away by removing the generic 
method and 
replacing it with an overload. I have no idea why the generic gives ngen so 
much 
trouble, and only for the signed version. I would suspect an ngen bug were it 
not 
for the signing thing, but I'm thinking perhaps there is some kind of security-
related issue regarding the generation of the actual generic implementation?

I can't find a lot of good information about what's actually going on and 
searching 
for the error messages ngen produces doesn't turn up much. I'm going to think 
about 
this more, but it looks like removing the generics might be the way to go. I'd 
like 
to know why it can't cope before I seriously think about doing that though.

Original comment by josh.petrie on 23 Jan 2009 at 7:22

GoogleCodeExporter commented 8 years ago
Wow, very interesting. If you send me a SlimDX.dll with the generic 
SetRenderState
removed then I can try to reproduce the error on my end.

Thanks a lot.

Original comment by holyfuzz...@gmail.com on 23 Jan 2009 at 1:09

GoogleCodeExporter commented 8 years ago
.method public hidebysig instance valuetype SlimDX.Result 
SetRenderState<T>(valuetype 
SlimDX.Direct3D9.RenderState state, !!T 'value') cil managed
{
    .maxstack 5
    .locals (
        [0] valuetype IUnknown* unknownPtr)
    L_0000: ldarg.0 
    L_0001: call instance valuetype IUnknown* SlimDX.ComObject::get_UnknownPointer()
    L_0006: stloc.0 
    L_0007: ldloc.0 
    L_0008: ldarg.1 
    L_0009: ldarg.2 
    L_000a: box !!T
    L_000f: unbox int32
    L_0014: ldind.i4 
    L_0015: ldloc.0 
    L_0016: ldind.i4 
    L_0017: ldc.i4 0xd4
    L_001c: add 
    L_001d: ldind.i4 
    L_001e: calli method unmanaged stdcall int32 modopt([mscorlib]System.Runtime.CompilerServices.IsLong) 
modopt([mscorlib]System.Runtime.CompilerServices.CallConvStdcall) *(native int, 
uint32 
modopt([mscorlib]System.Runtime.CompilerServices.IsLong), int32)
    L_0023: ldnull 
    L_0024: ldnull 
    L_0025: call valuetype SlimDX.Result SlimDX.Result::Record<class 
SlimDX.Direct3D9.Direct3D9Exception>(int32, object, object)
    L_002a: ret 
}

.method public hidebysig instance valuetype SlimDX.Result 
SetRenderState<T>(valuetype 
SlimDX.Direct3D9.RenderState state, !!T 'value') cil managed
{
    .maxstack 5
    .locals (
        [0] valuetype IUnknown* unknownPtr)
    L_0000: ldarg.0 
    L_0001: call instance valuetype IUnknown* SlimDX.ComObject::get_UnknownPointer()
    L_0006: stloc.0 
    L_0007: ldloc.0 
    L_0008: ldarg.1 
    L_0009: ldarg.2 
    L_000a: box !!T
    L_000f: unbox int32
    L_0014: ldind.i4 
    L_0015: ldloc.0 
    L_0016: ldind.i4 
    L_0017: ldc.i4 0xe4
    L_001c: add 
    L_001d: ldind.i4 
    L_001e: calli method unmanaged stdcall int32 modopt([mscorlib]System.Runtime.CompilerServices.IsLong) 
modopt([mscorlib]System.Runtime.CompilerServices.CallConvStdcall) *(native int, 
valuetype 
_D3DRENDERSTATETYPE, uint32 
modopt([mscorlib]System.Runtime.CompilerServices.IsLong))
    L_0023: ldnull 
    L_0024: ldnull 
    L_0025: call valuetype SlimDX.Result SlimDX.Result::Record<class 
SlimDX.Direct3D9.Direct3D9Exception>(int32, object, object)
    L_002a: ret 
}

Original comment by josh.petrie on 24 Jan 2009 at 3:23

GoogleCodeExporter commented 8 years ago
Above you will find the IL from Reflector for SlimDX's SetRenderState<T>, the 
method that is causing 
ngen.exe to fail. The top method is SlimDX's SetRenderState actually calling 
the native LightEnable method 
(because that method takes parameters that can be compile-time static-cast'd, 
just like the native 
SetRenderState). The bottom method actually calls SetRenderState.

You can see they do not differ except in the actual method invoked (L_0017 
loads the offset, L_001e makes 
the call). This is why I chose LightEnable, to try and coerce the C++/CLI 
compiler in to generated IL that was 
as similar as possible. 

The top method is handled fine by ngen.exe. The bottom method crashes it with 
E_FAIL. This is starting to feel 
more and more like an ngen.exe bug.

I can't send you a SlimDX.dll without the generic because I'd have to write a 
ton of overloads for you to be 
able to compile your project against the DLL. 

Original comment by josh.petrie on 24 Jan 2009 at 3:28

GoogleCodeExporter commented 8 years ago
I'm inclined to agree that it sounds like an ngen bug. Perhaps something in the
native SetRenderState is tripping up ngen. Unfortunately we can't fix either 
ngen or
native DirectX. Perhaps I'll submit a bug report to Microsoft, but I doubt this 
would
be a high priority for them.

If I have the time, I might take a peek at the SlimDX source myself and create 
some
non-generic overloads. If so, I'll let you know how it goes.

Again, thanks for all your help looking into this issue.

Original comment by holyfuzz...@gmail.com on 24 Jan 2009 at 3:44

GoogleCodeExporter commented 8 years ago
We suspect this is an ngen.exe bug and will attempt to get in touch with MS 
about 
it. Unless hear back otherwise, I'm going to close this as wontfix.

Original comment by josh.petrie on 24 Jan 2009 at 4:10