Жесткий разбор работы потока nvwgf2umx.dll для DX11 и DX12
На DX12-трейсе в MXA видно, что активность отдельного nvwgf2umx-поток не коррелирует с количеством Present(DXGI) и не выглядит как обязательный повторяющийся этап на каждый кадр. Это уже намекает, что данный поток не участвует в кадре напрямую (фото 1).
Далее проверяется поток рендера: коллстак на участке сабмита содержит D3D12Core.dll!CCommandQueue::ExecuteCommandLists, далее исполняется код nvwgf2umx.dll, затем путь WDDM через dxgkrnl.sys (DxgkSubmitCommandToHwQueue / DXGHWQUEUE::SubmitCommand). Это означает, что UMD NVIDIA исполняется в контексте потока приложения и сабмит проходит inline внутри потока рендера (фото 2).
Чтобы исключить, что submit мог не относиться к рендерингу самого кадра, в WPA открываются Microsoft-Windows-DxgKrnl → QueuePacket, где ThreadId совпадает с потоком рендера, а PacketType указан как DXGKETW_RENDER_COMMAND_BUFFER. Следовательно, именно поток рендера сабмитит рендерные командные буферы (фото 3).
Отдельный nvwgf2umx-поток может присутствовать и выполнять фоновые задачи, но не является обязательным звеном сабмита RENDER_COMMAND_BUFFER; рендерный сабмит выполняется в потоке рендера приложения, включая исполнение части кода UMD.
Отдельный nvwgf2umx-поток может присутствовать и выполнять фоновые задачи, но не является обязательным звеном сабмита RENDER_COMMAND_BUFFER; рендерный сабмит выполняется в потоке рендера приложения, включая исполнение части кода UMD.
На DX11-трейсе в MXA размечаются Present(DXGI) win:Start / win:Stop (понадобится позже), основной поток игры, поток рендера и отдельный nvwgf2umx-поток (фото 4).
Коллстак nvwgf2umx-потока показывает наличие пути сабмита в HWQueue, но это всё ещё требует верификации типа пакета (фото 5).
В WPA открывается Microsoft-Windows-DxgKrnl → QueuePacket. ThreadId совпадает с nvwgf2umx-потоком, а среди событий присутствует PacketType = DXGKETW_RENDER_COMMAND_BUFFER. Это подтверждает, что в DX11 отдельный nvwgf2umx-поток действительно сабмитит рендерные командные буферы и участвует в пайплайне рендера кадра (фото 6).
На полном DX11-таймлайне видно разделение стадий: работа основного потока и рендер-потока относится к подготовке кадра, а события вида MMIOFLIP / IndependentFlip и MMIOMultiPlaneOverlay* относятся к этапу показа/scan-out (дисплейный стек, MPO). MMIOMultiPlaneOverlay* — конец обработки, обновление состояния наложений вывода (фото 7).
Отдельно важно не смешивать “submit” и “DPC”: сабмит виден как путь через ZwGdiDdDDISubmitCommandToHwQueue → dxgkrnl, тогда как DPC/ISR характерны для обслуживания событий показа (vblank/flip/scan-out) и сигнализации в дисплейном стеке, а не как универсальная отправка команд в смысле submit.
Следующий пост будет об аффинити для этого потока