Saturday, January 26, 2013

Pixel shader expecting shader resource view

I have been experimenting with a game engine and 1 "Ubershader" as an effect for all materials. The "Ubershader" enabled several features like diffuse, specular (Blinn and Phong models), normal maps, texture maps... for all materials. The output-window of my visual studio environment kept spamming me with a lot of D3D10 INFO messages in the line of:
D3D10 INFO: ID3D10Device::DrawIndexed: The Pixel Shader unit expects a Shader Resource View at Slot 1, but none is bound. This is OK, as reads of an unbound Shader Resource View are defined to return 0. It is also possible the developer knows the data will not be used anyway. This is only a problem if the developer actually intended to bind a Shader Resource View here.  [ EXECUTION INFO #353: DEVICE_DRAW_SHADERRESOURCEVIEW_NOT_SET]
Root cause for these INFO messages was that not all textures were bound (used) for every material. I found a solution to remove these INFO messages with the creation of different techniques and different pixel shader declarations, e.g.:

// Default Technique
technique10 Default {
    pass p0 {
        SetRasterizerState(NoCulling);
        SetVertexShader(CompileShader(vs_4_0, MainVS()));
        SetGeometryShader( NULL );
        SetPixelShader(CompileShader(ps_4_0, PSDefault()));
    }
}

// Diffuse texture technique
technique10 TexturedDiffuse {
    pass p0 {
        SetRasterizerState(NoCulling);
        SetVertexShader(CompileShader(vs_4_0, MainVS()));
        SetGeometryShader( NULL );
        SetPixelShader(CompileShader(ps_4_0, PSDiffuseTexture()));
    }
}

// technique: Normal texture, Diffuse texture and Blinn model
technique10 NormalTexturedDiffuseSpecularBlinn {
    pass p0 {
        SetRasterizerState(NoCulling);
        SetVertexShader(CompileShader(vs_4_0, MainVS()));
        SetGeometryShader( NULL );
        SetPixelShader(CompileShader(ps_4_0, PSNormalTexturedDiffuseSpecularBlinn()));
    }
}
The corresponding Pixel shader functions thus become:

// Pixel shader Default
float4 PSDefault(VS_Output input) : SV_TARGET {
    return PS(input, false, false, false, false);
}

// Pixel shader Diffuse Texture
float4 PSDiffuseTexture(VS_Output input) : SV_TARGET {
    return PS(input, false, true, false, false);
}

// Pixel shader Normal Texture, Diffuse Texture and Blinn model for specular component
float4 PSNormalTexturedDiffuseSpecularBlinn(VS_Output input) : SV_TARGET {
    return PS(input, true, true, true, true);
}
The "main" pixel shader then looks like something as:

// The Pixel Shader
float4 PS(VS_Output input, uniform bool bHasNormalTexture, uniform bool bHasDiffuseTexture, uniform bool bSpecularBlinn, uniform bool bHasTextureSpecularLevel) : SV_TARGET {
          ...
//NORMAL
 float3 newNormal = CalculateNormal(input.Tangent, input.Normal, newTexCoord, bHasNormalTexture);
//DIFFUSE
 diffColor += CalculateDiffuse(newNormal, bHasDiffuseTexture, newTexCoord);
//SPECULAR
 specColor += CalculateSpecular(viewDirection, newNormal, newTexCoord, bSpecularBlinn, bHasTextureSpecularLevel);
  
           ...
return float4(finalColor, opacity);
}
After I refactored the effect in the above way, I effectively removed all related D3D10 INFO messages. Nevertheless, the effect got a bit more complicated: it looks like there will be a lot of different techniques required if our materials will be a combination of various different features from the ubershader. But this is probably a subject on its own. Maybe someone holds a more elegant solution?

For a correct understanding of the problem, I'm still looking for an interpretation of these specific D3D10 INFO messages and if they inform the developer of an impact on the performance of the effect. If the unbound resource views are totally harmless, then why would we want these kind of INFO messages?
A clean output window seems to come at a high price given the increased complexity of the effect.