userData can be used in many ways. This value is set from the shader compiling method. Its best utility is to diferenciate the behavior of the shader on set callbacks, for instance, to use the same callback with many diferent shaders.
"There is nothing truly useless, it always serves as a bad example". Arthur A. Schmitt
Mel I also found it really useful to control the branching in a shader. It's great for lighting when you need certain things to react and certain things to ignore certain lights, without writing a new shader.
If we had better control over materialparams, for example a parameter which is a pointer where we can control the pointer type, there would be a ton more flexibility with shader design.
(also, technique support, but that may be a XNA only thing)
when i need pointers, i put them as attributes in the shader callbacks, and set them as soon as posible, being the optimal moment on the callback creation time. I use the userData for instance to enable or disable the shadowmapping variable setting for shaders that behave the same, but one has shadowmapping and the other doesn't.
"There is nothing truly useless, it always serves as a bad example". Arthur A. Schmitt