Something is puzzling me a little at the moment, and I'm hoping someone can clarify the issue for me.
I'm unsure about the relationship betwen btGjkPairDetector and btGjkEpaSolver. It appears that btGjkPairDetector::getClosestPoints does an initial GJK test to determine whether two objects intersect, and then btGjkEpaSolver uses the EPA algorithm to calculate the penetration depth. However, btGjkEpaSolver also seems to repeat the initial GJK test to find a simplex enclosing the origin, not using the result from btGjkPairDetector. It appears that btGjkPairDetector::getClosestPoints includes more degeneracy handling so it is almost as if it is providing an initial, more robust, version of the test done again in btGjkEpaSolver. So is this something that needs a refactor to do reduce the duplication, or have I just completely missed the point?
In addition, it doesn't appear that the GJK separating axis/search vector is actually cached from one iteration of collision detection to the next. Is this a relatively simple task that would allow non penetration cases to be reject much quicker? It seems to me that there is some complication in doing this, specifically for collision detection with triangle meshes, as the triangle mesh is represented as a single collision shape but ideally you would want to cache a separating axis for each triangle (or perhaps just a few, with a lifespan), in contrast to most collision shapes which are not a collection of primitives.
Am I also right in thinking that only a single manifold is maintained for collision against a triangle mesh - is it not relatively easy then for a 4 point manifold to be insufficient, as an object can have several discontinuous contacts with a concave triangle mesh?
I'm still getting to grips with everything, but if I could better understand these issues it would help me focus on where I might be able to contribute

edit: meant concave, wrote convex.