VIsual C++ generates redundant code of inline function in Release mode

Started by
1 comment, last by maxest 11 years, 4 months ago
Hey guys,

In my cross-renderer I have a function that sets shader's constant:

inline void CRenderer::setVertexShaderConstant_ogl_d3d9(const string& name, const mtx& m)
{
#ifdef RENDERER_OGL
if (!currentShaderProgram->setMatrix(name, m))
{
SAFE_CALL(Renderer_outputMessageFunction)(string("WARNING: There is no uniform with given name or it's not used in the shader"));
SAFE_CALL(Renderer_outputMessageFunction)("\tVertex shader: " + currentVertexShader->name);
SAFE_CALL(Renderer_outputMessageFunction)("\tUniform name: " + name);
}
#elif RENDERER_D3D9
currentVertexShader->constantTable.setMatrix(D3D9Device, name, m);
#endif
}


Now, in my rendering loop I call this function:

renderer.setVertexShaderConstant_ogl_d3d9("worldTransform", worldTransform);
renderer.setVertexShaderConstant_ogl_d3d9("viewProjTransform", viewProjTransform);


It works fine. The problem is that when I switch to D3D10 renderer (whose source is empty in this function) VC++ generates some redundant code for it.

This is assembly when these two lines are commented out:

; 210 : // renderer.setVertexShaderConstant_ogl_d3d9("worldTransform", worldTransform);
; 211 : // renderer.setVertexShaderConstant_ogl_d3d9("viewProjTransform", viewProjTransform);


And the assembly when these two functions are called:

; 210 : renderer.setVertexShaderConstant_ogl_d3d9("worldTransform", worldTransform);
push OFFSET ??_C@_0P@KOAAPGHC@worldTransform?$AA@
lea ecx, DWORD PTR $T190163[esp+392]
call DWORD PTR __imp_??0?$basic_string@DU?$char_traits@D@std@@V?$allocator@D@2@@std@@QAE@PBD@Z
lea ecx, DWORD PTR $T190163[esp+388]
call DWORD PTR __imp_??1?$basic_string@DU?$char_traits@D@std@@V?$allocator@D@2@@std@@QAE@XZ
; 211 : renderer.setVertexShaderConstant_ogl_d3d9("viewProjTransform", viewProjTransform);
push OFFSET ??_C@_0BC@FADNJIOD@viewProjTransform?$AA@
lea ecx, DWORD PTR $T190164[esp+392]
call DWORD PTR __imp_??0?$basic_string@DU?$char_traits@D@std@@V?$allocator@D@2@@std@@QAE@PBD@Z
lea ecx, DWORD PTR $T190164[esp+388]
call DWORD PTR __imp_??1?$basic_string@DU?$char_traits@D@std@@V?$allocator@D@2@@std@@QAE@XZ


My intuition would be that if the function is empty for D3D10 renderer and it is inline, the compiler will simply skip it, but it doesn't. Any idea why?
Advertisement
In order to call your function, you're constructing a [font=courier new,courier,monospace]string[/font] object from a [font=courier new,courier,monospace]const char[][/font] object. The compiler doesn't know whether that constructor/destructor causes any side-effects, so it can't remove that bit of code in order to be sure it hasn't changed the meaning of your program.

Change your [font=courier new,courier,monospace]setVertexShaderConstant[/font] function to take a [font=courier new,courier,monospace]const char*[/font], or alternatively, convert the literal text into [font=courier new,courier,monospace]string[/font] objects in advance (instead of every call), and the useless code should go away.

Personally, I don't use a string class at all, but that's probably controversial advice.
Yup, that was it. I moved strings outside the render loop and it's fine.
I've already experienced strings slowness. So far I use them for instance as keys to maps in my OpenGL's shader program implementation, so that I don't need to call glGetUniformLocation each time I want to set a uniform. But I think I will look for better ways to handle that.
Thank you very much for the explanation!

This topic is closed to new replies.

Advertisement