Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

GraphicsDevice.RenderTargetCount should be implemented on WebGL projects #2197

Open
vchelaru opened this issue Jan 25, 2025 · 2 comments
Open

Comments

@vchelaru
Copy link

vchelaru commented Jan 25, 2025

Kni web is missing GraphicsDevice.RenderTargetCount. This is important for FlatRedBall to detect if there is a current render target so that it can create an internal stack when drawing post processing.

As a workaround I can do:

    var renderTargetCount = 0;
#if WEB
    renderTargetCount = Renderer.GraphicsDevice.GetRenderTargets().Length;
#else
    renderTargetCount = Renderer.GraphicsDevice.RenderTargetCount;
#endif

Unfortunately this seems to allocate internally, so it's slightly more expensive than a potential Count property.

I am doing a workaround for now, but it would be nice to have something a little more efficient.

This is on WebGL, I haven't tested the other Kni platforms.

@vchelaru
Copy link
Author

vchelaru commented Feb 6, 2025

I realize that the problem is actually that XNA did not include a RenderTargetCount, but MonoGame has one.

I understand now why it may not exist, but...what kind of performance implications does Renderer.GraphicsDevice.GetRenderTargets().Length; have? Is there an alternative way to check whether there is a non-null render target active?

@nkast
Copy link

nkast commented Feb 18, 2025

RenderTargetCount and GetRenderTargets(RenderTargetBinding[]) were added in MG as a zero-alloc alternative to GetRenderTargets(). In any real scenario you would need to keep a copy of the bindings.
In fact, you are calling GetRenderTargets() again in the same method.
https://github.com/vchelaru/FlatRedBall/blob/63815277f114a5470911a4577b3be68012ea3321/Engines/FlatRedBallXNA/FlatRedBall/Graphics/PostProcessing/PostProcessLogic.cs#L32-L42
The RenderTargetCount property is not useful on it's own and increases the API surfaces without reason.

The first change was to combine the two methods by returning the number of bindings from GetRenderTargets(RenderTargetBinding[]).
#2213
FNA seem to have done something similar with GetRenderTargetsNoAllocEXT(RenderTargetBinding[])
FNA-XNA/FNA@d9bd938

The second change was to return a preallocated zero-length array from GetRenderTargets() , making zero-allocs when there are no bound rendertargets.
#2212

I propose two paths,
a) Combine the two calls to GetRenderTargets() into one call. This would half the allocations.
In the upcoming version it would have zero allocations when there are no current rendertargets.

b) use GetRenderTargets(RenderTargetBinding[]) . That is the only way to have zero-alloc in all cases.
Allocate an array that is big enough to hold all rendertargets as a member to your class,
readonly RenderTargetBinding[] _previousRenderTargetBindings = new RenderTargetBinding[8].
call: renderTargetCount = Renderer.GraphicsDevice.GetRenderTargets(_previousRenderTargetBindings);

If you want something that would work with the current version, and doesn't need renderTargetCount, you could clear the array with Array.Clear(_previousRenderTargetBindings) before calling GetRenderTargets(RenderTargetBinding[]), then check (_previousRenderTargetBindings[0].RenderTarget == null)
Probably you can skip the check and assign previousRenderTarget directly!
previousRenderTarget = _previousRenderTargetBindings[0].RenderTarget as RenderTarget2D;

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants