What I have at the moment is in the vertex shader I'm creating a matrix to transform from tangent space to view space using the normal, binormal and tangent:
float4x4 gWorldView;
float3x3 mTangentToView;
Output.mTangentToView[0] = mul(float4(Input.mTangent, 0.0f), gWorldView).xyz;
Output.mTangentToView[1] = mul(float4(Input.mBinormal, 0.0f), gWorldView).xyz;
Output.mTangentToView[2] = mul(float4(Input.mNormal, 0.0f), gWorldView).xyz;
Then in the pixel shader I sample the normal map and transform it to view space using the mTangentToView matrix:
float3 normal = gNormal.Sample(gSampler, Input.mTexCoord).rgb;
normal = (2.0f * normal) - 1.0f;
normal = mul(normal, Input.mTangentToView);
Output.mNormal = normalize(normal);
And for reference, this is what I was doing to calculate the face normal, where mPositionView is the view space position:
Output.mNormal = normalize(cross(ddx_coarse(Input.mPositionView), ddy_coarse(Input.mPositionView)));
Here are screen caps showing the result of the normal mapping and just using face normals:
Normal Mapping
Face Normals
[edit] Turns out it was a problem with the model not the code, edited post to save bumping