protonscr

UMA Adapter on Steam Deck not exposed correctly

vkd3dclosed
HansKristian-Work/vkd3d-proton#1215 · opened 2022-09-03 by sherief · updated 2022-09-09 · 8 comments · github
Ssherief 2022-09-03 github

I'm working on a project planning to support Steam Deck as a first-class problem, and I've noticed a missing optimization opportunity:

  • On PC with discrete GPUs, every frame's vertex data subject to CPU processing is copied to vidmem via a high priority copy queue, then the main graphics queue waits on its signal and proceeds to render the frame. On UMA architectures and systems that expose ReBAR (currently via NVAPI), this copy can be avoided entirely. For processed data (procedural etc.), the output can be written directly to UMA or PCIe over ReBAR. For decompression, data can be decompressed directly into UMA memory, but not ReBAR (since the compress might read-back while decoding, and this is very slow over PCIe / write combined memory).

Currently, Steam Deck reports the UMA field of D3D12_FEATURE_ARCHITECTURE's D3D12_FEATURE_DATA_ARCHITECTURE struct as FALSE, and so the engine fails to apply the relevant optimizations.

Ddoitsujin maintainer 2022-09-04 github

The Steam Deck is not a UMA device from a Vulkan point of view, so it's rather hard for us to really detect this without hard-coding it specifically for the Deck. The device reports itself as having 6GB of dedicated VRAM.

I'm also not entirely sure what kind of implications reporting an UMA device has on D3D12 heap creation rules, we might be forced into code paths that may be suboptimal on a driver level.

It should also be noted that we cannot support WriteToSubresource / ReadFromSubresource for images in a performant manner since Vulkan currently has no such functionality. The current implementation uses images with LINEAR tiling (which are slow), we're planning to rewrite this using a GPU submission (which will make readbacks stall until the GPU has completed its work).

As for ReBAR, it's rather unfortunate that D3D12 has no way to explicitly make use of that (Vulkan does). The NVAPI extension obviously won't work on the Deck out of the box, however we could wire it up and enable that code path once your application actually ships on the Proton side.

Ssherief 2022-09-04 github

It's great to hear you're open to ReBAR support - I only mentioned it as a reference point, I was actually considering experimenting with adding an IVKD3DDevice interface that I can get via QueryInterface on the D3D12 device and then using that to create custom heaps. Would this be technically possible? I can understand if it's not desired ofc given the project scope and priorities.

Images, even with UMA, are tricky since swizzling / tiling formats are hardware specific, but the use case for UMA that ReBAR doesn't cover is decompression of buffer data used for rendering. If reading buffers from upload heaps during rendering is free (i.e. doesn't incur PCIe traffic) on Deck then I should be good to go if I can somehow reliably detect when I'm running specifically on Deck.

Ddoitsujin maintainer 2022-09-04 github

I was actually considering experimenting with adding an IVKD3DDevice interface that I can get via QueryInterface on the D3D12 device and then using that to create custom heaps. Would this be technically possible?

We already have an extension interface, which is currently used by Proton's nvapi implementation to enable DLSS support: https://github.com/HansKristian-Work/vkd3d-proton/blob/master/include/vkd3d_device_vkd3d_ext.idl

Extending this by adding a ID3D12DeviceExt1 should be easy enough, actually implementing support for HVV allocations is going to be somewhat tricky though since we already have a heuristic in place to allow HVV allocations for UPLOAD heaps, so any interactions there will need to be considered.

HHansKristian-Work maintainer 2022-09-05 github

It should be theoretically possible to expose an extended CreateHeap that does ReBAR as:

  • DEFAULT (current heuristic behavior)
  • OFF (Forces host memory)
  • ON (Forces ReBAR even if budget is exhausted)

There is this PR that would allow us to toggle rebar on a per-allocation basis https://github.com/HansKristian-Work/vkd3d-proton/pull/1092. However, going down the "vendor hack extension interfaces" is murky.

Reporting UMA would indeed be weird since Steam Deck has a memory type layout that looks more like a dedicated GPU, even if device local vs non-local is somewhat trivial (I believe?).

It should also be noted that we cannot support WriteToSubresource / ReadFromSubresource for images in a performant manner since Vulkan currently has no such functionality. The current implementation uses images with LINEAR tiling (which are slow), we're planning to rewrite this using a GPU submission (which will make readbacks stall until the GPU has completed its work).

Indeed, this is a good reason why exposing UMA might be problematic if it tricks apps into going down these paths.

The Steam API has a way to query if you're running on Deck, so it would make sense to do that I think.

It should probably be easy to expose the VkPhysicalDeviceType as INTEGRATED or DEDICATED. I believe APUs should report as INTEGRATED, and that might be a better hint when to skip staging buffers or not.

Mmisyltoad maintainer 2022-09-05 github

It should also be noted that we cannot support WriteToSubresource / ReadFromSubresource for images in a performant manner since Vulkan currently has no such functionality. [...] We're planning to rewrite this using a GPU submission (which will make readbacks stall until the GPU has completed its work).

A VK extension for this sort of behaviour is long overdue, would probably be better for us to focus on something like that instead of rewriting this to be still crap.

Ddoitsujin maintainer 2022-09-05 github

@Joshua-Ashton games are broken right now due to this so we need to deal with this anyway.

Ssherief 2022-09-08 github

Thanks for the replies everyone - this answers all my questions about Steam Deck support, looks like there won't be any issues for my implementation. Feel free to close this bug unless you'd like to use it for feature tracking.

HHansKristian-Work maintainer 2022-09-09 github

I think it's fine to close this as there is no concrete action to be taken here I think. If there is one later, feel free to open a new issue.