RenderTarget2D limitations?

Hi,

First, a thank you to all those who maintain the Monogame framework. It is a great framework.

Is there a limit to how many RenderTarget2Ds you can use or have in a game? I don’t want to box myself into a corner later in development. I remember reading something in the past about xbox limitations? I don’t see why there would be, it is just a child of Texture2D with IRenderTarget. The primary system this is for is PC but I might release on xbox or playstation.

Background on why:
My game has the ability for the player to design a lot of stuff. I have a texture merge process in my game. Rather than using GetData/SetData on textures, I merge textures in a RenderTarget2D once and cache that texture in the entities render component. This way all draws just simply draw one texture instead of layers. One draw loop might take a small hit to make a cached texture but all next draw loops after never have to deal with it.

I currently can render about 7000 entities and maintain 60fps with SynchronizeWithVerticalRetrace and IsFixedTimeStep set to true IN debug mode. Also collision detection is running, menus, AI logics and various other systems. Also this is all with an i5 with cpu graphics (I think 4400).

Thanks,
David

Maximum target count for using multiple-render-targets is generally what you need to worry about. Realistically you shouldn’t run out of render-targets without doing something really nuts, and if you did you’d just have to split up compositing to reuse targets.

IIRC there isn’t a fixed limit on render-targets, it’s just about how much VRAM you want to give to them.

Do be aware that using large render-targets for layers like you’re doing eats a lot of fill-rate. You’re pushing pixels for each target with whatever alpha overhead you already have for sprites, and then later pushing an entire render-target as what for practical purposes is a huge sprite.

It shouldn’t be a big deal unless you start pushing heaps of particle effects through on different layers - since overlapping particles chew fillrate. The budget that would go into shadow maps you put into layers.

1 Like

How many Rendertargets are you using/do you need ?
Even in high end engines like UE4, they rarely use more than a dozen (for the main rendering I mean, postprocess effects may need their own like chromatic aberrations, dirt lensflare etc), and not all at the same time in the multi-render target process.
If you are doing 2D only, it is likely you won’t need as much as this.

You may also be able to render far more entities with instancing, if not already done.

Thanks for the replies.

@AcideFaucent
This wouldn’t be used for particle effects and the max texture size would be 1024px and that would be rare. I’ll have to monitor the fill-rate. Thanks for the heads up.

@Alkher
Zero to many really, I can’t control what the player might do. The game is 2D. I’m using RenderTargets as intended (for main rendering purposes) but started to experiment with them as a way to generate a run-time texture that could stored. It is nice to just draw other textures to a canvas and store that canvas versus the GetData/SetData approach (and then coloring them, agh).

Hmm, maybe I should just go back to the GetData/SetData. It is only called once, when a player is doing customizing.

For layers, there is a depth or layer (I cannot verify this, not on my computer at the moment) parameter with spritebatch.draw, with valid values in [0, 1] i think. You would just have to normalize the layer height/place in the list to get this value and draw on top or under for almost free.
Or maybe i did not understand at all your problem

Thanks, I’m already doing layers on the draw too using FrontToBack. Sorry. Maybe I’m asking it wrong. I just wanted to know about any limitations of rendertargets. Like is it best practice to keep them limited in usage. Has other developers had problems with xbox or playstation with X amount of rendertargets.

Just a more solid example of why I’m doing it:
The problem comes when I have lots of game entities on the screen which all have layers to draw on them. For example, an army with lots of npcs. Each npc may have different accessories to make it uniquely render. If there are 1000 npc entities in battle, each have 10 accessories, it would 1000*10 draws which starts to impact performance.

So what I did was make each npc entity during equipping action (runtime), create its own unique image once (using rendertargets or SetData/GetData, both work fine and cause no performance problem). So instead of drawing 1000 entities with 10 layers of accessories. I’d always be at the big O of NPC’s drawn.

1 Like

About your npc usage example it sounds like you’ll get a lot of repeating textures (for example a goblin with a sword) which would appear multiple times. So I propose using a dictionary of render targets, where the key is a long string representing the final appearance of the npc (eg something like “goblin_sw02_arm05_hair32”) and value is render target + how many NPCs using it (so you can remove it when it’s no longer used).
That way you can reduce render targets count.

About your general question I wonder too, I used render targets to build chuncks of the level which are made from lots of small sprites on top of each other and are static. Hope someone have a good answer…

For you npcs, you definitely need to use instancing, which will reduce your draw calls to… 11. 1 for the npc and 10 for the number of accessories you have to draw. (sorting them manually, but sorting 10000 entities is not so slow)

As said before the number of rendertargets is principally limited by the memory available.
And the more you have the more they will eat the bandwidth (send A, then send B, then C etc slows down the rendering) and their size the fillrate.
But you have virtually no limit on their number.

Multirendertarget can also help, filling up to 8 rendertargets at a time. For ex one RT for the background, 1 for npcs, 1 for trees and all things with alphatest, 1 for projectiles and particles.
All the ‘depth/layer’ sorting done manually on the cpu or using spritebatch

That’s what i have always used till now, with adjustments of course to match the needs of the game. This may not be the best method, but it runs really fast. (about 100000 models in one draw call which could be even bigger with sprites only as no face culling occurs, and less than 4ms to sort with multithreading them before drawing)

@Alkher,

Awesome thanks. I will look into instancing. I actually never heard of it until this discussion.

Multirendertarget can also help, filling up to 8 rendertargets at a time. For ex one RT for the background, 1 for npcs, 1 for trees and all things with alphatest, 1 for projectiles and particles.
All the ‘depth/layer’ sorting done manually on the cpu or using spritebatch

+1 Already doing it.

Thanks everyone.