# HLSL MipMap sampling in pixel shader

Using the Texture2D.Sample function, how does the pixel shader infer the mipmap level to use? Or does it use mipmap level 0? I am using the ps_4_0 shader model. And replacing Sample, with SampleLevel(state, pos, 0.0), does that give same results? In what cases does it give same results?

struct PS_INPUT
{
float4 pos                   : SV_POSITION;
float3 tex : TEXCOORD0;   // texture coordinate
};

struct PS_OUTPUT
{
float4 color                   : SV_Target0;
};

Texture2D tex;

SamplerState state {
Filter      = MIN_MAG_LINEAR_MIP_POINT;
};

PS_OUTPUT main(PS_INPUT input) : SV_Target
{
PS_OUTPUT output;

output.color = tex.Sample(state, input.pos);

return output;
}


Sample calculates the mip level to sample based on screen space derivatives of the texture coordinates provided. Derivatives of texture coordinates can be computed as follows:

float2 derivX = ddx(myTexCoord.xy);
float2 derivY = ddy(myTexCoord.xy);


But this is hidden inside the Sample function implementation. You can achieve the same result by using SampleGrad function and providing the derivatives yourself:

float4 textureColor = myTexture.SampleGrad(mySampler, myTexCoord.xy, derivX, derivY);


If you use SampleLevel, that expects the mip level instead of the derivatives, but you could compute a mip level from the derivatives yourself and use SampleLevel:

float delta_max_sqr = max(dot(derivX, derivX), dot(derivY, derivY));
float mip = 0.5 * log2(delta_max_sqr) * myTexture_NumberOfMIPLevels;
float4 textureColor = myTexture.SampleLevel(mySampler, myTexCoord.xy, mip);


However the SampleLevel might not give the exact results of the Sample method because Sample can use a different method based on the sampler descriptor's MipFilter and MipLODBias settings.

Use case:

Calculating derivatives using ddx and ddy needs information from neighbour pixels, so you can't use the functions inside dynamic branches or loops (which are maybe not running for neighboring pixels). In those cases the derivatives could be precomputed and you can use the SampleGrad or SampleLevel instructions inside the dynamic branches/loops.

• As long as you are comfortable requiring D3D_FEATURE_LEVEL_10_0 or higher, this works. – Chuck Walbourn Jan 24 '18 at 17:59