SharpDX multiple material performance and basic effect test

Just like I was afraid of, my test model of a room:

room1

probed to be insanely expensive when drawing with textures. I’m building the mesh using Assimp, by creating a model object with the next structure:

  • Model -> Root node (empty in this case)
    • Child node -> Mesh
    • Child node -> Mesh
      • Child node -> Mesh
    • Child node -> Mesh

Each mesh points to a material structure, containing colors, opacity, effectID and textures. The room in the image contains 45 materials, and 45 meshes/nodes + the root node.

Rendering only the duck with texture I got around 520 FPS, wich is great. Rendering the room gave 18 frames per second! I know that FPS is not a good performance measure, but it was obvious that something was really wrong. To have a more reliable test I loaded the room in DX Studio, and, obviously, the framerate was a lot higher (60 FPS) so… what was wrong? Some Googling was needed.

And after searching about performance, the only thing I found that I’m not doing already is “effect cloning”. I narrowed the performance bottleneck to the parameter assigning on the effect, so I thought that maybe having separate effects would help somehow… wrong. First, I discovered that the parameters weren’t being passed properly to the effect. Reason: the Material structure. It is passing as copy! Only classes pass by reference. Changed to Material Class. Still, the performance remains the same, wich is really bad. I wonder if it is my fault, or maybe the effects have to be managed in a different way in SharpDX to avoid the huge performance drop. Probably is my fault, so I will re check everything and optimize all as much as I can.

FastForward three days >>>>

So I checked my code, changed a few things and… fail. My last hope was to check the SharpDX forum to see if somebody had the same problems, and guess what: The Forum is closed!

(I posted my thoughts about that on other post)

Anyway, it turns out that the problem with my horrible performance was uniquely related to the fact that I was passing the parameters to the shader using this line:

effect.setvalue(value)

I already knew that doing that (not specifying the parameter type) was not recommended. After checking every parameter type and setting the line accordingly, the performance raised to 60 FPS, slightly higher than the framerate delivered by DX Studio. Hurray! 😀 The right way to pass parameters is with this:

effect.setvalue (of T)(value)

Also, writing:

effect.setvalue (of boolean)(booleanvalue)

Causes an exception, It must be:

effect.setvalue (of bool)(booleanvalue)

But…

I discovered that the actual performance drop was tied to me passing the parameter as object, using a function like this:

sub seteffect (byref handler as effecthandler,byref value as object)
effect.setvalue(value)
end sub

Internally, the object was passed using the generic function, instead of the right ones. I solved switching based on the type of the value:

sub setEffect (byref handler as effecthandler, byref value as object)
If TypeOf (paramValue) Is Boolean Then
effect.SetValue(paramHandle, DirectCast(paramValue, Boolean))
elseif TypeOf (paramValue) Is Matrix Then
effect.SetValue(paramHandle, DirectCast(paramValue, Matrix))
elseif
...
endif
end sub

This gives the maximum speed. As comparison, passing the value as object gives me 13 frames/second on my NVIDIA GTX 560 se, while passing the values after the cast gives me 990-1000. Sweet!

Of curse you could use function overloads, if you like. I just don’t like having that much code.

On a final note, passing a null value also drops the perf near to zero.  Watching for that now.

Advertisements