When you say non-changing sprites, do you mean that not even the position is changing? If you can put all sprites into a static vertex buffer, then 100K is nothing, unless they are large, in which case pixel fill rate will kill performance.
If you need to upload 100K sprites every frame to the GPU, I guess you’re somewhere in a grey zone, where performance will suffer noticeably, but it’s probably still doable.
Well, that’s an interesting coincidence. How about two million moving ones:
However, for your purpose 200 000 of static this isn’t needed. It is of course absolutely possible, as Markus said, fill rate will be your bottle neck way before anything else.
As Willmotil said, using insanced quads is 100% way to go, you will use single quad in binding of first vertex buffer and array of whatever struct you need (at least position, possibly scale, possibly also UV offset in case of multiple sprites per texture) of given quantity as second binding. I’ve scrolled through Willmotil example and I believe it should work fine.
Assuming the space you’re drawing them to fits in a single screen…
Another option might be to just render them all once, or in batches, to a RenderTarget2D. If their positions, rotations, and scales never change independently this would probably work. For colour, if you’re not particular about the draw order, you could probably just render the new one with the new colour to the render target when needed and carry on.
If the space you’re drawing them to is larger than a screen, and you only need to view portions of them at a time, look into a QuadTree to partition your world space. This will allow you to only draw what’s visible.
Other than that… I should get around to learning how instanced quads work one of these days