The project is split into several parts:
- The kernel driver, with simple 3D command forwarding and 3D resource allocation
- The userland driver, in fact the OpenGL backend
- The reference, explaining virtio-gpu commands
https://github.com/Keenuts/virtio-gpu-win-icd
https://github.com/Keenuts/virtio-gpu-documentation
https://gitlab.com/spice/virtio-gpu-wddm/virtio-gpu-wddm-dod
(another repo: https://github.com/Keenuts/virtio-gpu-win/)
For the one interested, here is en entry about this project:
http://studiopixl.com/blog/index.php/posts/3d-acceleration-using-virtio
OpenGL ICD (Installable Client Driver) is a fancy name for an OpenGL implementation. This one is pretty simple, and is only here as a POC.
OpenGL* : OpenGL entry points, GlBegin, GLEnd, etc...
State* : This is the state-tracker. We only deal with high level structures
Virgl* : VirtIO related parts. This part focus on the actual commands we want to send to the driver
DriverAPI* : This is the part focused on driver communication. How can we communicate with the kernel, or test-suite if in debug.
Simple example:
On a context creation, I call wglCreateContext. Go straight to the wrapper(opengl.cpp). Then state-tracker. Check if context exists, what do I need to create it, and send VIRGL_CREATE_CONTEXT commands. Also need to create and attach some resources. Once commands are ready, time to send something to the kernel. For this, we need to use D3DKMT_Escape function.
In the kernel, we check the command, and can submit it through the Virtio queues, and hope for the best.
For now, we can submit 3D command buffers on the host. To comminicate with the kernel, we must use the Escape function. Commands are composed of a head, and a payload.
Head (UINT32) | Payload |
---|
4 Values are supported OPENGL_ICD_CMD_ALLOCATE (2), OPENGL_ICD_UPDATE (3), OPENGL_ICD_FREE (4), OPENGL_ICD_TRANSFER (1)
This command is used when the ICD wants to send a command to the host. No checks are done, and the command is directly sent to the host through the CtrlQueue
- OPENGL_ICD_TRANSFER
struct {
UINT32 head; //OPENGL_ICD_TRANSFER
UINT32[] cmd; //the command
}
These commands are used to create buffers on system's memory. Using these buffer, you can use the backing attachment command. The only way to update buffer content is to send a UM allocated buffer and use OPENGL_ICD_UPDATE command.
- OPENGL_ICD_CMD_ALLOCATE
struct {
UINT32 head; //OPENGL_ICD_CMD_ALLOCATE
UINT32 size; //size of the buffer to create
UINT64 handle; //OUT parameter: the handle
}
- OPENGL_ICD_UPDATE
struct {
UINT32 head; //OPENGL_ICD_UPDATE
UINT64 handle; //the handle previously grabbed from OPENGL_ICD_CMD_ALLOCATE
UINT32 size; //size of the data
VOID *data; //UM data pointer
}
- OPENGL_ICD_FREE
struct {
UINT32 head; //OPENGL_ICD_FREE
UINT64 handle; //the handle previously grabbed from OPENGL_ICD_CMD_ALLOCATE
}
This ICD support the most important VirGL and virtio-gpu commands.
- Virtio-gpu commands
- createContext
- deleteContext
- createResource2D
- createResource3D
- attachResource
- detachResource
- unrefResource
- VirGL commands
- createSubContext
- setCurrentSubContext
- deleteSubContext
- Clear
- setViewportState
- createObject
- bindObject
- bindShader
- setViewportState
- setScissorState
- setPolygonStipple
- setFramebufferState
- setConstantBuffer
- inlineWrite
- drawVBO
This very basic state-tracker let you create a context, setup basic OpenGL features (viewport, scissor, stipple..). You can then create a VBO, and hopefuly, display some vertices.
- Extend the commands supported by the ICD
- Add a proper state-tracker on top of this API
- Add security / thread-safety !
- Be able to get feedback from VirGL commands