As I mentioned in my introduction, I've done a lot of "theoretical" shader work, so chapter 2 ("Direct3D Pipeline") was mostly a refresher - thankfully my understanding/knowledge of the general D3D pipeline matches what Wolfgang Engel has to say about it.
At this point I'll also recommend an additional point of reference that you can all get at. The "HLSL Hands-On Workshop.ppt" powerpoint presentation that is included in the Microsoft GDC 2005 slides download contains a good coverage of the pipeline. Slides 3, 4 and 5 in particular.
Tip Number 1
You need to understand how the Direct3D pipeline works before you get too deep into this stuff. In some respects it's just plain stupid to try and customize something if you don't know how it normally works. It makes the programmable pipeline a lot easier to understand if you know how the inputs and outputs map between the many stages.
After confirming that I did know my pipeline, I moved onto the higher level concepts of the HLSL. By this I wanted to learn where my data goes. It seems that a lot of the tricky syntax involved is simply a generalised mechanism for converting/passing the data along the pipeline.
By data I mean the raw geometry that my program will be creating, and the vertex shader will be operating on. I'm completely ignoring the actual modification process.
Data will start off in my C++ program, either generated by some C++ code or loaded from a file (e.g. as a mesh). My program will then pack it into an IDirect3DVertexBuffer9 as binary data, maybe for good measure some indices can be composed as an IDirect3DIndexBuffer9. The important realisation here is that the data stored in the VB or IB (which is quite likely to be located in VRAM) is just a big lump of 1's and 0's.
Square brackets group 8 bits together, to indicate each byte
So my C++ program creates a declaration that describes (via offsets, tags and indices) the layout of the binary data stored in the VB. It passes this over to Direct3D which will consequently know how to work with the raw binary.
The binary data now colour coded according to the declaration.
The first twelve (red) bytes being the position
The second twelve (green) bytes being the normal
The next eight (blue) bytes being the texture coordinate
Finally, the first 3 (red) bytes of the next vertex in the stream
That's not it though!
The HLSL code that makes up the vertex shader is written in it's own (C-like) language. There are two mappings required here - into the and out of the code. Whilst it's not direct (due to other pipeline stages existing), there is correlation between the declaration my C++ code passes to the D3D runtime and the data that can be read in by the vertex shader. In truth, the semantics specified by this mapping are hints to the compiler so that it can line up the assembly code accordingly.
A similar process occurs when the vertex shader code has completed - outward semantics map the variables/data used by the shader code to the hardware registers so that the hardware has the correct information in the correct place ready for the next stage of the pipeline.
To summarise this process, I drew this diagram up:
Click on the image to enlarge
The green arrows show the flow of data along the pipeline
The red arrows show the mappings between different stages