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

Is D3D12MA::Allocator::BeginDefragmentation() Work Correctly ? #63

Open
FlyAndNotDown opened this issue Apr 28, 2024 · 4 comments
Open
Labels
question Further information is requested

Comments

@FlyAndNotDown
Copy link

Our in-house engine use D3D12MA as D3D12 backend's native memory allocator, and I found that placed memory fragments get more and more with game running. By read document, I found there is a interface called D3D12MA::Allocator::BeginDefragmentation can help heap allocation defragment. But after transplanted code from official sample, I just got some overlapped placed resources in heaps, like this in NSight Graphics:

image

Our resources' copy, create, access and destroy can happened on multi-thread, and resources' lifecycle is managed by intelligent pointers, but I have checked if a defragment action scheduled, any of resources' operation will blocked by mutex, and old resources' ref count will be set to 0 after defragment action.

So I got puzzled, I can not find any meaningful code on web except official sample, is D3D12MA really support defragment ? Could you have some more complex sample which can shared with us ?

@adam-sawicki-a adam-sawicki-a added the question Further information is requested label May 6, 2024
@medranSolus
Copy link
Collaborator

Hi!

Could you please provide steps that you are using for defragmentation? Generally speaking, after starting defragmentation all resources that are selected to move (listed in DEFRAGMENTATION_PASS_MOVE_INFO passed into DefragmentationContext::BeginPass()) are needed to be recreated in new places so older resources will be released and their ID3D12Resource pointers will be invalid. These steps are also described in here. Since you are using multiple threads for that, you must ensure that after committing single defragmentation pass (calling DefragmentationContext::EndPass()) all your own routines are using correct pointers to new resources. This will require some synchronization to ensure no hazards. You can also look at the tests methods for more examples on how to use defragmentation.

@FlyAndNotDown
Copy link
Author

FlyAndNotDown commented May 6, 2024

Sorry about I forget to update this issue. I have checked if use many locks and some hard code to limit all the thing executed in a strict order, the library work correctly. Now what confuse me is the document specific that user need flush all graphics commands to make sure old allocation's data copy to the new one before DefragmentationContext::EndPass(), which is OK when wait fence every frame, because after flush we can update resource pointers and recreate resource views easily, when record graphics commands next time, everything is ready, no outdate resources are used. Unfortunately our in-house engine use inflight commit model, which means there are many command list executing inflight. Inflight model can brings some annoying problems, e.g. DefragmentationContext::EndPass() will release allocation after swap defragment src and dest, but at most time the resource is still used in inflight command list, so we can only defer the release process, which made lifecycle management bad.

For some reason, I can not show you code. So for inflight model, any suggestions ? Your reply is helpful for me, thanks!

@medranSolus
Copy link
Collaborator

Hi, currently there is no mechanism that would allow for synchronization of such case where there might be several overlapping command lists that use resources used for defragmentation. Solution I can think of would be to set selected resources that are in flight to ignore them in current defragmentation pass or postponing executing such pass by few frames, which will result in delay in calling EndPass().
Some other mechanism that I can think of but would require changes inside the library would be to add possibility to postpone deletion of resources by few frames while switching to newly created ones for further frames. Would that sound like a desired solution?

@FlyAndNotDown
Copy link
Author

Sounds feasible, I will try those mechanisms later, thanks you.

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

No branches or pull requests

3 participants