Software renderer for Managed DX9?

Is there a fast software renderer that is DX9 compatible? I'm looking into Pixomatic and SwiftShader, and while they are D3D9.dll replacements, I am using Managed DirectX from C#.

Is is even possible to make Manged DirectX use an external D3D9.dll?

If so, how would I make it work with either Pixomatic or SwiftShader?

If it is not, can anyone suggest a good sw renderer we can use?

We are trying to make a sw version to run on laptops that don't have fast video chips.

[502 byte] By [PierreMaloka] at [2007-12-25]
# 1

I've not heard of anyone doing it. The docs imply that is you pass DeviceType.Software into device creation it should work. However there is no managed API for calling IDirect3D9::RegisterSoftwareDevice so you would have to make your own wrapper.

However if pixomatic works by replacing d3d9.dll then MDX should work just fine since its just a wrapper around d3d9.dll

I've seen this question come up before so I would love to know the results of your experiments - drop me an email (zman@thezbuffer.com) or reply here.

TheZMan at 2007-8-31 > top of Msdn Tech,Game Technologies: DirectX, XNA, XACT, etc.,Game Technologies: Graphics...
# 2

There is a real pluggable software device available from Microsoft

RGBRast: http://www.microsoft.com/downloads/details.aspx?FamilyID=57d03491-6c49-4429-bff7-130408b5f410&DisplayLang=en

But as ZMan already said the method to register it is not public. But it should not that hard to write a small interop method for this job. I am sure you would not find another one as the interface for pluggable devices was never documented.

I am not sure about the pixomatic interface but switftshader have a D3D9.DLL replacement.

<shameless plug>

If you want upgrade to D3D10 in the future ask me about my D3D10 software device.

</shameless plug>

RalfKornmann at 2007-8-31 > top of Msdn Tech,Game Technologies: DirectX, XNA, XACT, etc.,Game Technologies: Graphics...
# 3
I came across this thread searching for the ability to use SwiftShader with managed DirectX 1.1. (The end result is to enable software rendering for old machines that don't support DX9, or for particular configurations that disable D3D, such as over remote desktop connections.) The software device from Microsoft would provide the same basic software rendering functionality so I've attempted to use the Microsoft Direct3D9 software rasterizer (mentioned in the previous post) with managed DirectX, but this doesn't seem possible.

The RegisterSoftwareDevice method is provided by the IDirect3D9 object which is not directly accessible in managed code. In managed code the common features of the C++ IDirect3D9 interface are provided by the Microsoft.DirectX.Direct3D.Manager class, but the RegisterSoftwareDevice method is not one of them. The MDX 2.0 beta had the method added to the Manager class, but MDX 2.0 will not be an option since it won't be released.

The fundamental issue is that the IDirect3D9 instance cannot be directly accessible in managed code. I'd guess that this object is instantiated when needed for certain Manager method calls and for device creation and manipulation which is handled by the Device object. It is possible to pinvoke the IDirect3D9 RegisterSoftwareDevice method directly; however, the software device won't be registered for the managed IDirect3D9 instance which is inaccessible.

Is there a way to invoke the software device registration method on the private IDirect3D9 instance that managed code uses?

(I can successfully call the register device method by directly using pinvoke, or by creating a c++ wrapper dll, but I'd guess the managed DeviceType.Software will never be available since different IDirect3D9 instances will be used. I have also successfully used the software device in unmanaged code so I know that works.)

Taberh at 2007-8-31 > top of Msdn Tech,Game Technologies: DirectX, XNA, XACT, etc.,Game Technologies: Graphics...
# 4

This is a little hack. It’s bad and ugly but it does the job:

[Guid("81BDCBCA-64D4-426d-AE8D-AD0147F4275C"), InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]

public interface ID3D9

{

int RegisterSoftwareDevice(IntPtr fnction);

// No reason to add the rest of the interface

}

public partial class Form1 : Form

{

public Form1()

{

InitializeComponent();

IntPtr hRast = LoadLibrary("RGB9Rast_1.dll");

IntPtr D3D9GetSWInfo = GetProcAddress(hRast, "D3D9GetSWInfo");

FieldInfo info = typeof(Manager).GetField("m_lpUM", BindingFlags.Static | BindingFlags.NonPublic);

IntPtr D3D9Ptr;

unsafe

{

D3D9Ptr = new IntPtr(Pointer.Unbox(info.GetValue(null)));

}

ID3D9 D3D9 = (ID3D9)Marshal.GetTypedObjectForIUnknown(D3D9Ptr, typeof(ID3D9));

int error = D3D9.RegisterSoftwareDevice(D3D9GetSWInfo);

if (error != 0)

return;

PresentParameters presentParams = new PresentParameters();

presentParams.Windowed = true;

presentParams.SwapEffect = SwapEffect.Discard;

Device device = new Device(0, DeviceType.Software, this, CreateFlags.SoftwareVertexProcessing, presentParams);

}

[DllImport("kernel32.dll")]

static extern IntPtr LoadLibrary(string lpFileName);

[DllImport("kernel32.dll", CharSet=CharSet.Ansi, ExactSpelling=true)]

public static extern IntPtr GetProcAddress(IntPtr hModule, string procName);

}

RalfKornmann at 2007-8-31 > top of Msdn Tech,Game Technologies: DirectX, XNA, XACT, etc.,Game Technologies: Graphics...
# 5
Very nice, that's excellent, thanks! (It does get the job done. :)

Using reflection to check for private static members of the Manager class I saw the "m_lpUM" field of type "IDirect3D9*", but I couldn't imagine how to use the correct managed instance to register the software device. I spent more than a few hours playing with interop components, all the while seemingly taking shots in the dark. The System.Reflection.Pointer was new to me so I didn't know what to do with it. Can this pointer type only be used in unsafe code blocks?

One other thing I noticed is that the Manager class has a private static method named "RegisterSoftwareDevice", which I thought was promising and tried to invoke it directly using reflection. At first I incorrectly guessed the single parameter type as IntPtr, but after examining the parameter information I found the single parameter to be a delegate type. (The MDX 2.0 public method used IntPtr.) So I never came across a solution to convert an IntPtr returned from a GetProcAddress call to a managed delegate type. Is that type of conversion possible in .Net 1.1? (I thought I'd ask anyway since I was stuck on this for a while, and you clearly display a high familiarity with .Net interop. :)

I did find that .Net 2.0 provides a new capability specifically for this, Marshal.GetDelegateForFunctionPointer, and it seems like it might get the job done. However, being that I'm currently using .Net 1.1 it wasn't an option. Did you happen to see this private method and/or try to use it? (Perhaps with .Net 2.0 this method can be easily used and unsafe code blocks might not be necessary. You're code example above defined a partial class, so it was using .Net 2.0, but I can confirm that it works the same for 1.1.)

Thanks again!

Taberh at 2007-8-31 > top of Msdn Tech,Game Technologies: DirectX, XNA, XACT, etc.,Game Technologies: Graphics...
# 6

The Pointer type itself could be used outside unsafe blocks. The Problem is that Unbox returns void* and pointer are limited to unsafe blocks.

I am tried "RegisterSoftwareDevice“ first but I always got an exception therefore I go the other way.

RalfKornmann at 2007-8-31 > top of Msdn Tech,Game Technologies: DirectX, XNA, XACT, etc.,Game Technologies: Graphics...