bo3b / 3Dmigoto

Chiri's DX11 wrapper to enable fixing broken stereoscopic effects.
Other
688 stars 109 forks source link

Getting Resource in 3Dmigoto code using hash #175

Open AkaShrug opened 9 months ago

AkaShrug commented 9 months ago

sorry in advance since this is not really an issue just wondering if 3dmigoto has something in code that can get resource from hash (my knowledge in c++ very limited but from what i saw it was always opposite like getting hash from resource) some games leave debug names and my plan was to try to get them like https://stackoverflow.com/questions/57694038/how-to-get-back-the-name-passed-to-id3d12objectsetname but i couldnt find way to go from hash to resource (other than going through G->mShaders or G->mResources) but from my tests it is just slow and not reliable (specially on shader usages dump)

DarkStarSword commented 9 months ago

This is something I've wanted to add for a long time, and never got around to, partly because I'm not sure the names are going to be available most of the time - I thought that depended on the DX debug layer being enabled, though perhaps I'm mistaken if it just uses Set/GetPrivateData APIs for this (I could have sworn the debug layer had a dedicated API for this through a different COM interface, but I can't find doco on that now so perhaps I'm mistaken). Unfortunately, those APIs are ones that we have previously identified as being extremely slow - we've previously had a contributor use them to implement some new features, but the performance regressions that were reported against that release forced us to revert that change and find other solutions.

We do actively use those APIs for some things today, and as long as they aren't added to any hot paths or kept strictly in code that is only run in frame analysis / shaderusage dumps (or at the very least only used when hunting is enabled) it might be ok.

ShaderUsage is kind of meant to be a historical record of what resources have been seen used together - the resources it records have been seen in the past, but may not exist at present, which I think is where your reliability issues trying to look up those hashes in mResources are probably coming from, since they may not exist by the time you try to find them.

It might make sense to add these to is G->mResourceInfo since that is a map from hash to info about the resources (but not the resources themselves), but that is mostly filled out when the resource is created, and AFAIK the debug names are set in a separate call after that point. We could potentially set them in that data structure when they are encountered during HackerContext::RecordGraphicsShaderStats(), as that is where we record most of the stats that end up in ShaderUsage.txt, and is only active while hunting is on with the OSD displayed, and when DumpUsage is enabled as a compromise for performance. That call can already noticeably drop fps in some games when active, and if getting the names here adds too much additional overhead we might need to also gate them on some other setting, or add caching to avoid the call any more than needed.

Alternatively, we could hook the SetPrivateData() API and use that to record the names into G->mResourceInfo when they are set. I guess doing it that way would make an already slow call even slower, and it's not like we can do GUID comparisons much faster than Microsoft... hard to say whether it's a better or worse option than recording the name when we see it used :-/

Whatever you go with, it's worth keeping in mind that many distinct resources with different names might end up all sharing the same hash. In fact, I don't think this will be rare at all - I actually expect to see this quite frequently (think - multiple GBuffers that all share the same size, format, etc, but are used for different purposes). So, we might end up needing to add an std::(unordered?)set to mResourceInfo/struct ResourceHashInfo to store multiple names for each hash... This might complicate any caching strategies we try though...

In the case of adding the names to frame analysis log files you should have access to the resource so shouldn't need to look it up by hash - in some ways this might be the best place to add these names without having to be concerned about performance, and there won't ever be any ambiguity with hashes mapping to more than one name since you are working with the specific resource directly. My biggest concern here is not so much the performance as it is inadvertently breaking tools that other modding communities have written that make use of the frame analysis data (like my blender_3dmigoto.py script, which now has been forked by multiple modding communities to adapt to the needs of the specific games they are interested in). Changing the log file is probably going to be mostly ok (and would be a very welcome addition), but changing the filenames could well break things.

The overlay would also be a nice place to display these names, though it might be hard to avoid taking a performance hit to achieve this.

If you can get this working is it something you might consider submitting a pull request for? I think it would definitely be a welcome addition if we can find a good way to integrate it and keep any performance issues under control.

DarkStarSword commented 9 months ago

Actually, thinking about this some more I think the possibility of having multiple resources with different names sharing the same hash is probably a good reason to avoid looking these up by hash since you might end up recording the name of an irrelevant resource that happened to have the same hash as the actual resource that was used.

For the hunting overlay it may still make sense to look these up by hash since it cycles through hashes and doesn't differentiate between multiple buffers that have the same hash, but perhaps if we add it here it should be stored alongside the mVisited and mSelected globals...

For ShaderUsage.txt it might be better to store them in the ResourceSnapshot struct I think, since that is already there to sort out issues with resources being freed before dumping out ShaderUsage.txt

AkaShrug commented 9 months ago

ShaderUsage is kind of meant to be a historical record of what resources have been seen used together - the resources it records have been seen in the past, but may not exist at present, which I think is where your reliability issues trying to look up those hashes in mResources are probably coming from, since they may not exist by the time you try to find them.

i think more or less why , if the call itself is slow and there are too many resources only noticed this since copying with dump_usage enabled would create ShaderUsage and it was beyond slow 5-10 seconds

In the case of adding the names to frame analysis log files you should have access to the resource so shouldn't need to look it up by hash - in some ways this might be the best place to add these names without having to be concerned about performance, and there won't ever be any ambiguity with hashes mapping to more than one name since you are working with the specific resource directly.

this probably best place to add , i only needed to look up via hash in shader dump WriteHLSL and overlay but despite that i really didnt notice much performance hit on overlay even when i was going through all mResources/mShaders to find the current selected one resource and show name if it existed

If you can get this working is it something you might consider submitting a pull request for? I think it would definitely be a welcome addition if we can find a good way to integrate it and keep any performance issues under control.

sadly not really , much of what i did was testing to see how feasible the idea is and i really didnt test many games (few unity games like PGR) not sure how often those names are kept to justify being added (even if optional) or how useful it would be and that probably means it is limited to unity games