A cross-encoder concatenates the query and one candidate passage and runs them through the model together, producing a relevance score for that pair. It solves the problem that independent embeddings cannot represent how a specific query relates to a specific passage. It exists as the accurate but expensive half of retrieval: accurate enough to reorder a shortlist, too slow to search a corpus with.
A bi-encoder encodes the query and each passage independently into vectors, and relevance is their similarity. It solves the problem that a cross-encoder must run once per candidate, which is impossible against a large collection. It exists as the half of retrieval that can be precomputed and indexed, at the cost of losing the interaction between query and passage.