utmapp / utmapp/UTM

[Proposal] Writing a Streaming Vulkan Driver

Open
#5,561 43 comments 3 reactions 0 assignees View on GitHub
enhancement virgl
Dominant language
Swift
Stars
35.5k
Forks
1.8k
Avg merge
5d 5h
Merged PRs (30d)
7

Description

In response to #4551

Instead of trying to modify virglrenderer to work on MacOS, or wait for gfxstream to support MacOS, I was thinking of making a Vulkan driver that will stream Vulkan commands over TCP/IP to the host's MoltenVK.

Advantages:
- This will replace venus, not virglrenderer, so we will have complete control over behavior
- Venus, the current vulkan driver for virtualized guests, does not simply send commands over, either a. does some driver-specific behavior before sending the command, or b. does not send the command at all
- This will lead to massively simplified code-base, relative to venus+virglrenderer
- It would be easier to debug/develop on, as communication would happen completely in the guest, so there would be no need to restart QEMU after making a change.

Potential issues:
* Some commands have arguments that are pointers (in fact, I'm pretty sure things like VkImage are pointers themselves). Currently, I was thinking of just dereferencing them and encoding/decoding them as integers. However, if it is possible that even after a command returns, pointers will be modified, that will be a problem --- we would somehow need to keep track of when pointers are modified and transfer them as needed.
* Or is this not an issue (even if a image is modified by MoltenVK after the command completes, you would have to send another command to return the modified image, instead of working the pointer directly)?
* SOLVED (partially): Vulkan handles are handled directly by the device, and should not be accessed/modified directly by the host, so there's no need to specially handle them (we can just derefence them, cast them into ints and send them). Info/auxiliary structs will work similarly (however, instead of just casting them, we will first deep-copy all pointers, then marshal the new pointer, then deep-assign the return, unless it's `const`). The problem is how to deal with potential memory addresses, most notably in `vkMapMemory` --- how do you map between guest and host without going through QEMU?
* SOLVED (mostly): Using `fopencookie` on Linux, and `funopen` on BSD (in the future), we can virtualize file operations. `read` will read from the matching pointer at the remote host, `write` will do the same for writing.
* We can then mmap it into a `void *`, which can then be casted to the different object types
* If one of a struct's members is a pointer, or a function's argument is a double pointer, we create another pointer (basically, creating a pointer for each level).
* Each guest-to-host mapping will be held in a map in the host daemon. When a request comes in to read/write from a guest pointer, the operation will be done, as-is, on the location on the guest.
* Most of the proposed codebase would be codegen (most likely in Python). We would need some way to parse the headers to get command name, arguments, whether they are pointers, and the definitions of the arguments. Maybe there's something like this for Python?
* For `vkcube` at least, there would have to be some MacOS specific modifications to least one function (e.g, MoltenVK returns the surface extension for Metal, but in Linux guests, vkcube expects the surface extension for that display platform). This shouldn't be too hard to overcome, though, especially compared to the previous issue
* SOLVED: Just use Vulkan's registry xml, which was designed specifically for this.

If there's anything else that comes to mind, I'll edit this (I was thinking about this over the weekend, by I only collected my thoughts into something coherent while writing this).

Contributor guide

Open the contributing guide

Assessment

This issue has not been assessed yet.

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.