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

Strange vertex buffer dumping #355

Open
GhostyPool opened this issue Jan 8, 2025 · 3 comments
Open

Strange vertex buffer dumping #355

GhostyPool opened this issue Jan 8, 2025 · 3 comments

Comments

@GhostyPool
Copy link

GhostyPool commented Jan 8, 2025

I have come across a few games all with very similar engines (highly modified ue3) that exhibit strange vertex buffer dumping behavior. These games I've tested are: Mortal Kombat X, Mortal Kombat 11 and possibly Injustice 2 (although not tested)

I did a frame analysis using dump_vb share_dupes clear_rt, which works fine in other games, but here I noticed the following:

  • IBs dumped: 1400
  • VBs dumped: 641 (all with low vertex counts like 3, 6, 24, 84, etc.)
  • All vbs are only vb0 with no apparent high-poly mesh data

I also tried using ShaderOverride for a specific vertex shader but no VBs were dumped, I only got IBs. I’ve tried other options like deferred_ctx_accurate with no success while the blender plugin throws errors due to I'm assuming missing corresponding VBs for the IBs.

These games are known for their ue3 quirks so it wouldn't surprise me if it's some unusual rendering behavior. I will try using renderdoc to see if I can figure out any more details about this

Here are my frame analysis dumps:

MKx:
mkx.zip

MK11:
mk11.zip

@DarkStarSword
Copy link
Collaborator

DarkStarSword commented Jan 9, 2025

Unreal Engine can be a bit notorious for not using vertex buffers for some materials, and instead may use a structured buffer to pass vertex info that it indexes via SV_VertexID in the vertex shader (many UE materials actually use a combination of both vertex buffers and structured buffers, but some materials may only use one or the other).

I'd suggest dumping the vertex shader for some of those suspect draw calls and examine its code to see if it's doing something like that here, and enabling dump_tex buf (dump_tex actually means "shader resources", which includes buffers bound to SRV slots) to dump out any structured buffers the game may be using (and may as well throw dump_cb in the mix just in case they used a constant buffer for this, though that is unlikely, as indexing into constant buffers has really bad performance compared to structured buffers).

In particular I note this pattern in the log file of mkx for draw call 15:

000015 VSSetShaderResources(StartSlot:0, NumViews:1, ppShaderResourceViews:0x0000001A01DFF158)
       0: view=0x000001DDF9EE42F8 resource=0x000001DE423F53B0 hash=22913c51
000015 IASetVertexBuffers(StartSlot:0, NumBuffers:1, ppVertexBuffers:0x0000001A01DFF118, pStrides:0x0000001A01DFF160, pOffsets:0x0000001A01DFF180)
000015 VSSetShaderResources(StartSlot:1, NumViews:1, ppShaderResourceViews:0x0000001A01DFF158)
       1: view=0x000001DDF9EE40F8 resource=0x000001DE423F5F70 hash=8e869ea7
000015 IASetVertexBuffers(StartSlot:1, NumBuffers:1, ppVertexBuffers:0x0000001A01DFF118, pStrides:0x0000001A01DFF160, pOffsets:0x0000001A01DFF180)
000015 VSSetShaderResources(StartSlot:2, NumViews:1, ppShaderResourceViews:0x0000001A01DFF158)
       2: view=0x000001DDF9EE00F8 resource=0x000001DE423F6B30 hash=cff54db6
000015 IASetVertexBuffers(StartSlot:2, NumBuffers:1, ppVertexBuffers:0x0000001A01DFF118, pStrides:0x0000001A01DFF160, pOffsets:0x0000001A01DFF180)
000015 VSSetShaderResources(StartSlot:3, NumViews:1, ppShaderResourceViews:0x0000001A01DFF158)
       3: view=0x000001DDF9EDFF38 resource=0x000001DE423F50F0 hash=0875b4aa
000015 IASetVertexBuffers(StartSlot:3, NumBuffers:1, ppVertexBuffers:0x0000001A01DFF118, pStrides:0x0000001A01DFF160, pOffsets:0x0000001A01DFF180)
000015 VSSetShaderResources(StartSlot:4, NumViews:1, ppShaderResourceViews:0x0000001A01DFF1A8)
       4: view=0x000001DDF9ED6438 resource=0x000001DE4285FDF0 hash=6e032dda
000015 IASetVertexBuffers(StartSlot:4, NumBuffers:1, ppVertexBuffers:0x0000001A01DFF168, pStrides:0x0000001A01DFF1B0, pOffsets:0x0000001A01DFF1D0)

Note how this is interleaving calls to VSSetShaderResources and IASetVertexBuffers - that strongly suggests that this is a loop in UE's material code that is assigning both vertex buffers and structured buffers, and in there are no vertex buffers so it just clears those slots but assigned what I assume will turn out to be structured buffers instead to slots vs-t0 through vs-t4.

@DarkStarSword
Copy link
Collaborator

DarkStarSword commented Jan 9, 2025

I forgot to mention - even if you get the vertex data out of the game, my blender addon won't be able to process it out of the box. It should be possible to write something to either transform the data to look like normal vertex buffers that the addon will then be able to process, or potentially to extend the addon to import it directly, but because the structures buffers are game/material specific and lack any sort of metadata that the script could parse to determine what data is inside it* this generally can't be done in a game/material agnostic manner**.

* This metadata can sometimes be found in the reflection info inside the vertex shaders, but IIRC Unreal Engine strips that information out.

** I haven't studied the differences between games/materials closely enough - if we are lucky there might be some commonality between them that we might be able to use to handle some of these cases in a generic fashion, and there are some heuristics we could use to guess which fields are what (e.g. normals magnitude is always 1.0, forming points on a unit sphere).

Point is - extracting meshes from Unreal with 3DMigoto is an uphill battle.

@GhostyPool
Copy link
Author

After performing some dumps using dump_tex and inspecting the frame in renderdoc I can confirm that both games are binding large structured buffers to SRV slots (t0, t3, t5) like you have mentioned.

In RenderDoc I saw that the vertex shader SRV bindings are accessing structured buffers rather than VB slots for vertex positions or other data. The dumped vs-t3/t0 .buf files are also significantly larger (~899 KB) compared to others.

I believe I can write a python script to convert the .buf files into vb.txt files (by analyzing their structure in renderdoc) which the plugin then processes but of course this will be most likely specific to these games. I dont really have the knowledge to make a game agnostic approach either for now.

I will upload my dumps just in case you are interested in them
Mk11.zip

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