# Understanding DeviceContext and Shaders in Direct3D/SlimDX

I've been working through this tutorial about drawing triangles with SlimDX, and while it works, I've been trying to structure my program differently than in the tutorial.

The tutorial just has everything in the main method, I'm trying to separate components into their own classes. But I'm not sure where certain components belong: namely, contexts and shaders.

The tutorial (as it's just rendering one triangle) has one device, one swapchain, one device context and one set of shaders. intuition says that there is only one device/swapchain for one game, but with contexts I don't know.

I made a Triangle class and put the vertex stuff in there. Should it also create a context? Should it load its own shaders? Or should I pass some global context and shaders to the triangle class when it is constructed? Or pass the shaders and construct a new context?

I'm just getting started with 3D programming, so in addition to answering this question, if anyone knows of a tutorial or article or something about the larger-scale structure of a game, I'd be interested in seeing that as well.

• Have you tried XNA for 3D programming ? They have a lot of tutorials to get started! – brainydexter Feb 21 '11 at 19:49
• Let him be. SlimDx is for real man :]. – Notabene Feb 21 '11 at 19:53
• Yes, but I would like to get to know the subject on this level. – Carson Myers Feb 21 '11 at 19:54

You usually need one and only one device context for your application.

Generally this would live in some sort of 'Renderer' or 'Graphics' class, which would often be a singleton. This would handle initialisation/shutdown, and resetting the device on, for example, window resizing or fullscreen-windowed switches.

You really don't want a Triangle class with a Render() method and a lot of other stuff - which seems to be the direction you may be heading in? (I made this mistake with my first naive attempts at 3D rendering many years back, this really isn't good for performance!).

What you want is a 'Mesh' class that can contain an entire 3D object (hundreds/thousands of triangles) in a single vertex buffer, and draw it in as few DrawPrimitive calls as possible.

• Well, I wouldn't use the triangle to build larger objects -- I'd also have a Cube class, etc -- it has a single vertex buffer and a Draw() method which takes the device context. It sets the layout, topology and shaders on the context and then draws all the vertices in the buffer. This isn't good? – Carson Myers Feb 21 '11 at 20:14
• general rule of thumb is you want to minimize the Draw() calls regardless of the underlying API. For example if you wanted particle effects and such to just use 2 triangles, you would still want to try and put say 300 flame particles into a single buffer instead of 300 separate buffers. – James Feb 22 '11 at 1:35

Contexts are for threading. If you're not having fun with with multithreading, just use the Immediate context. Shaders are typically, you have one set of shaders for an application, and they can be re-used for different objects. You should not have contexts or shaders per object.

• alright, but what about context.VertexShader.Set()? How do I use a shader on a particular object if it's a part of the context? Also, I notice in context.Draw() you have to specify which vertices to draw. Do I create an object, set the context shader, draw the vertices from that first object, and then repeat for each object I want to draw? – Carson Myers Feb 21 '11 at 19:52
• You are setting the gpu. So you set one shader program. Actually you are setting technique which contains at least vertex shader and pixel shader. And you are setting one vertex data. Typicaly you are setting matrices, textures and another data too. Once you render it with context.draw, you are done with one render pass. Typicaly you are doing more render passes for one frame. One render pass for every material/effect means another data and another shader or same data and another shader. – Notabene Feb 21 '11 at 20:09