Handling shaders without D3DX

Started by
2 comments, last by Bearhugger 9 years, 11 months ago

Hi, I have a graphic rendering engine in DirectX9. Since D3DX has been deprecated, I'm working on removing it from the engine.

I was previously using ID3DXEffects to handle shaders. Without effect, it looks like I have to handle vertex and pixel shaders separately. This is not a big deal since I'm not using vertex shaders much anyway (2D game).

My problem is that, looking at the D3D9 API, there doesn't seem to be a way to access the different variables I am using in my shader. There is the IDirect3DDevice9::SetPixelShaderConstant family of methods, but they identify the parameters by index instead of a string. I'm not sure how I'm supposed to get the table that maps a variable name with its index? Another problem is I'm not seeing a function to set a texture variable in my code. I assume it has to do with samplers, but there's still an index I'm not sure what to do with.

Should I just assume that D3D9 is old so it's okay to use a deprecated (old) library (D3DX) with it, and stop worrying about having D3DX? Quite frankly, it looks like D3D9 shaders were designed to be used with D3DX, and it's hard to find doc about how to not use it since DirectX9 is starting to get old.

Advertisement

If you're comfortable with D3D9 and D3DX then stick with them. D3D9 isn't being updated any more, and neither is D3DX cool.png

To answer your question, you can either compile your shaders using D3DXCompileShader, or using fxc.exe ahead of time.

If you use D3DX to compile your shaders, you get a ID3DXConstantTable which tells you which indices match up with which names.

There's also options in fxc.exe to get it to tell you this information.

If you're not using D3DX's effects, then you should use this information to build your own name->index map structures for each of your shaders.

Alternatively, you can specify the indices to use when writing your actual shader code - e.g.

float myData : register(c0);//constant register #0

sampler myTexture : register(s0);//a texture in sampler register #0

And yes, in D3D9, "samplers" are texture slots.

Yea, there's no reasong to leave D3DX completely, if you're working with D3D9.

But moving away from D3DXEffect (and D3DXFont, D3DXSprite) can be a good idea, even if you still use the D3DX library for other stuff (texture loading, shader compilation, mathematics...). You don't really have a full control of what's going on with D3DXEffect and your own implementation can be more efficient.

As Hodgman said, you can use D3DXCompileShader/D3DXCompileShaderFromFile to compile a vertex or pixel shader and you'll get a constant table which will tell you which variables are assigned to particular registers. Then you can make your map from variable name to register type/index.

I'm personaly forcing some common parameters to specific register numbers, for example World transform is in c0-c3. This way I can easily set it from c++ and in HLSL it's simply defined as uniform extern float4x4 g_world : register(c0) (can be in an #include file).

This allows me to somehow emulate constant buffers from D3DX11, because when I have all camera parameters in adjacent registers, I can set them all using a single SetVertexShaderConstantF call. The same for material parameters etc.

All other parameters specific to a particular shader can be easily found using the constant table. But they must be in different (free) registers ;)

Btw, the D3DXEffect framework is very complex, it's not just about shaders. In fact it can be used purely with the fixed function pipeline to set render states.

I made a simple text file parser with my own syntax for technique definitions inside each effect (.fx file), so I can still use the ability to change render states per effect/technique. (These commands are in /* */ so the file can still be used by D3DXCompileShaderFromFileA without errors.)

Thanks a metric ton of the input, that was very enlightening. :)

I will most definitely take out the D3DX effects of my engine and handle the shaders manually.

This topic is closed to new replies.

Advertisement