Skip to content

Added pooling for Texture2D.PlatformGetData #8384

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

Open
wants to merge 8 commits into
base: develop
Choose a base branch
from

Conversation

Nebulaxin
Copy link
Contributor

This should fix #8304

@SimonDarksideJ
Copy link
Contributor

Can you address the remaining review comments @Nebulaxin , as this looks good to merge with those changes

@Peru-S
Copy link
Contributor

Peru-S commented Sep 3, 2024

Not sure if you saw @mrhelmut's comment about ArrayPool in BRUTE (only available when NativeAoT is). This looks good otherwise.

@ThomasFOG
Copy link
Contributor

From a personal perspective and coding style, I don't think that we need a pool and that a static byte array that we grow if needed is likely enough.

@squarebananas
Copy link
Contributor

Just a few thoughts:

  1. This change could also be made to the TextureCube class as well.
  2. Currently GetDataPool is a static inside Texture2D. As each instance of a pool will increase overall memory usage, GetDataPool could be moved & shared for use by other applicable classes.
  3. If GetData is performed on large resources of differing SurfaceFormats (if I'm understanding this correctly https://github.com/dotnet/runtime/blob/main/src/libraries/System.Private.CoreLib/src/System/Buffers/SharedArrayPool.cs), higher overall memory usage may occur because a pool is setup for each SurfaceFormat type.

From a personal perspective and coding style, I don't think that we need a pool and that a static byte array that we grow if needed is likely enough.

In terms of graphics planning, I believe one of the aims stated was to implement multithreaded graphics API support (such as drawing on one thread while using creating/set/get on others).

A static byte array could do this by implementing thread safe methods around it.

Looking at the ArrayPool<T> documentation though it says "this class is thread-safe. All members may be used by multiple threads concurrently (https://learn.microsoft.com/en-us/dotnet/api/system.buffers.arraypool-1?view=net-8.0).

So using ArrayPool<T> might simplify threading implementations and it also provide bucketing of similar array sizes along with a fast access tiered caching system (https://github.com/dotnet/runtime/blob/ad0c47c42e8901b9300701b237c42345b83c2bd9/src/libraries/System.Private.CoreLib/src/System/Buffers/SharedArrayPool.cs#L16).

For future consideration, I wonder if there would be any performance & memory allocation improvements if a single static ArrayPool<byte> was used across multiple class types?

@ThomasFOG
Copy link
Contributor

In terms of graphics planning, I believe one of the aims stated was to implement multithreaded graphics API support (such as drawing on one thread while using creating/set/get on others).

MonoGame isn't designed for that and currently uses graphics backends that are not friendly with that (especially OpenGL in this PR). Also, MonoGame already has thread-safety on those operations through Threading.BlockOnUIThread, although this is not real multi-threading and will stop threads and run operations back to back on the UI thread and then continue (because of how limited OpenGL is in that regard).

ArrayPool doesn't add much here beside using modern API. Even if we were using it, it wouldn't resolve the non-thread-friendliness of OpenGL.

I'm pretty sure that a single scratch buffer can be used across all kind of texture and surface types.

@squarebananas
Copy link
Contributor

Thanks for the reply. Just to make it clearer, the first 3 numbered points relate to this PR while the rest relates to ArrayPool usage "in terms of graphics planning" considerations in general.

I do understand that MonoGame isn't currently designed for this at all and that Threading.BlockOnUIThread still performs the backend graphics calls from a single thread at the moment.

In terms of graphics planning "for future consideration" though (so not this PR or OpenGL), I was suggesting ArrayPool might still be worth considering for multithreading benefits. These might be realized when accelerating load/build times by loading graphics resources across multiple threads and when any future async methods might increase the number of temporary buffers that concurrently exist.

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

Successfully merging this pull request may close these issues.

Getdata<T> allocates an extra array of T[]
6 participants