We generally want to minimise shader-program switches (
glUseProgram and all associated context changes) for the sake of performance. AFAIK it is not uncommon to render by shader program, i.e. group draw calls of all mesh instances that use the same set of shaders - or vertex shader at least (i.e. that have the same set of vertex attributes), for this reason.
How then do we go about doing both depth ordering and shader program changes, quickly? Because it seems to me one either orders primarily by program (thus minimal program context changes), or primarily by depth (frequent context changes), and that they're mutually exclusive in terms of maximising performance.
PS. In my current work I'm not using the hardware Z-buffer, instead I'm using the painter's algorithm prior to making all draw calls... If this affects the answer to the question at all, I'd be happy to hear solutions for both sorts of depth-ordering.