Thoughts on SlimDX 2: Interfaces

One of the biggest changes we’re going to make in SlimDX 2 concerns our use of interface types (specifically, our lack thereof). In the current version of SlimDX, the API consists almost entirely of concrete classes. However, there are advantages to exposing interfaces instead — improved testability of the public API and code depending on it, for example, as well as the potential for some back-end improvements to code health. There are two major main concerns involved in redesigning SlimDX to use interfaces:

The first is the question of how one initially obtains an interface. SlimDX 1 uses the constructors of its concrete objects to enable users to obtain new instances. Thus, in SlimDX 1 you would obtain a texture instance by doing new Texture2D( device, … ). This constructor will invoke the native ID3D10Device::CreateTexture(). In SlimDX 2, we’ll present a model that mirrors the native interface more closely, with an IDevice interface that demands a CreateTexture method.

To handle bootstrapping — obtaining that first interface — we’ll expose so-called “API objects” that will represent each of the primary subsystems SlimDX exposes to native code (for example, there will be a Direct3D10Api object that will let you obtain the initial D3D10 device interface. These API objects will also be a convenient location to present many of the native free functions. SlimDX doesn’t expose all of these now, and the ones it does provide are often tucked away, seldom-seen static members of one class or another.

The other half of the problem is translating those interfaces back into concrete, usable objects when they are passed back to SlimDX for one reason or another.

We could simply downcast the interface to the concrete type, but that relies on the assumption that such a cast would always succeed — and that isn’t true in general. SlimDX has always supported interoperation with other DirectX-wrapping managed libraries, and to make the assumption that our interfaces were only ever implemented by our own library would work against that.

Fortunately, as a result of that interoperability feature, we’ve had to have all of our objects expose their IUnknown or similar native pointer (wrapped up in a System.IntPtr). Thus, we can rely on an accessor for that pointer being available from the interfaces, and we can use that to obtain the actual interface we’re interested in working with in the SlimDX code.

One Comment

  • FWIW, I think I agree to this change. I’ve seen some remarks that SlimDX isn’t quite ‘slim enough’ in mimicking the native API and this change should go a long way in delivering the requested slimness. It’s probably also more transparent than wrapping stuff in concrete classes. I still remember the fun I had trying to figure out how they envisioned I should do occlusion queries back in MDX.

Post a Comment

Your email is never shared. Required fields are marked *