Writing an ICD is a problem in itself. Add to this Windows kernel interfaces, virtIO queues management, resources transfer between host and guest, and BOOM, you are lost. This brings us to our first step: something not efficient but simpler, API Forwarding.

Tasks

  • Hook OpenGL calls
  • Serialize function calls
  • Send them to the miniport-driver, then the host
  • De-serialize calls and execute them on the host.
  • Send some data back to the guest

Realization

ICD

The ICD part (Userland) is pretty straightforward. Make your own opengl32.dll, serialize the calls. Now find a sweet function in gdi32.dll to throw your mumbo-jumbo on the kernel side. Fortunately, we have this:

NTSTATUS APIENTRY DxgkDdiEscape(
  _In_ const HANDLE         hAdapter,
  _In_ const DXGKARG_ESCAPE *pEscape
)
{ ... }

A beautiful function available on both DOD and full display driver. It takes a pointer on an userland buffer, and send it to our display driver. Wait… userland buffer, no check, kernel part ? Mmmmm…. What could go wrong ?

Kernel part

To initialize a display driver, you must call a function: DxgkInitialize This function will take a big structure, containing function pointers to your driver. For a display only driver, you will have a reduced set of function to implement. And for a full featured driver, well…

Anyway, now the game is to run the driver, and see where we crash. Sadly we cannot just hope to add some functions, and run only using the working DOD code base. Windows wants something more, and the game is to find what, Yay ! Since we have a working DOD driver, let’s find how we could trick.

ICD <=> Kernel communication

We can register two type of driver: a DOD driver using DxgkInitializeDisplayOnlyDriver and DxgkInitialize. Windows will then know which kind of features each driver can support (fine tune will be done using query callbacks). Both drivers can implement DxgkDdiEscape. Great, we will fool Windows and use this DOD as a fully featured 3D driver ! WRONG !

Setup of the ICD part, sending everything through our escape functions ? check. But return values seams off. After investigation, and any function taking a userland buffer, I came to a conclusion: OpenGL ICD part cannot communicate with a DOD driver. Windows knows we are display only, and fall-back our ICD calls on it’s own driver.

So now, what’s the plan ? Let’s put this problem aside, and try to focus on the real part: create proper commands for the host.


See comments

On my arrival at the lab, I started a little project: working on a display only driver for Windows. A good way to start learning what was hidden under the hood of an OpenGL application. Google Summer of Code 2017 arrived, and subject were published. Among these, QEMU’s ‘Windows Virgl driver’. Great ! Let’s apply !

Applications closed early April. I took a look at the already existing DOD driver (non official repo)

and also decided to learn a bit more about Vulkan. Results came, and I was selected, excellent !

Mission

The idea is to bring 3d acceleration on Windows guests running with QEMU. Using VirtIO devices and Virgl3d.

Context

windows stack

On this stack, we can work on three parts: opengl32.dll, ICD and Miniport driver.

  • OpenGL32.dll is just a dynamic library used to communicate with out runtime driver.
  • ICD: this is the OpenGL implementation. This part is the equivalent of Mesa on Linux.
  • Miniport-driver: this is the kernel driver. Hardware specific, we are going to do our hypercalls here.

Problems

  • Windows is not open source. We have some basic ideas about D3DKrnl subsystem behaviour, but nothing is certain.
  • To develop a complete OpenGL state tracker is a lot of work.
  • Virgl3D takes some calls, and bytecode for shaders, re-translate it to GLSL, and call OpenGL again. Which means we will do the same work twice. Once on the host, once on the guest.

See comments

Vulkan is great, vulkan is love, vulkan is $(COMPLIMENT)

I heard a lot about this API, but never took some time to try it… So why not now ? The goal was to do a simple OBJ file viewer. Then, try to improve performances, and of course, since it’s Vulkan, go multithread! The API is pretty simple to use. We fill out some structs, and call a vkSomething function.

Some samples are available in the SDK, and of course, there is this Vulkan-tutorial website.

So commits after commits, the code grew, until the first “Hello, world !”: displaying a white triangle. 1000 lines of code vs 30, that’s quite steep. After some additional 7641 lines, here it us, a simple obj viewer!

GitHub link

R5D4 on Vulkan app under i3

But we are the May the 5th, and Google Summer of Code results are out! 🥳 Time to focus on the next big project: OpenGL driver for a Windows on QEMU VMs.


See comments

For my upcoming Vulkan project, I needed a model. So here it is ! R5D4, the unchosen droid from Star Wars.

Tools: 3ds Max, Substance Painter, Photoshop


See comments

My Erasmus took place in Spain, in a city near the coast. So each morning, seeing the sea reminded me how I never tried to work on water rendering.

This article made me want to also work on the buoyancy aspect. And because I was using Unity a lot at that time I decided to create a usable Asset.

Two constraints:

  • This asset had to work on every model.
  • It had to be easy to use on every ocean model

Here is the asset (free): ASSET-STORE LINK

And here are some preview:

screenshot in Unity 5


See comments