Skip to content

Commit 6a3ae8a

Browse files
authored
Merge pull request #12 from zjoasan/feat-igpu-shader-dxgi-keyed-mutex
feat(dxgi-shared-shader): integrate DXGI shared texture and keyed mutex for cross-GPU shader rendering
2 parents 37b2ed0 + 674d71f commit 6a3ae8a

File tree

3 files changed

+286
-1
lines changed

3 files changed

+286
-1
lines changed

Virtual Display Driver (HDR)/MttVDD/Driver.cpp

Lines changed: 244 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,7 @@ Copyright (c) Microsoft Corporation
4848

4949
#pragma comment(lib, "xmllite.lib")
5050
#pragma comment(lib, "shlwapi.lib")
51+
// #--- #pragma comment(lib, "d3dcompiler.lib")
5152

5253
HANDLE hPipeThread = NULL;
5354
bool g_Running = true;
@@ -131,7 +132,19 @@ wstring ColourFormat = L"RGB";
131132
// #--- // Microsoft::WRL::ComPtr<ID3D11RenderTargetView> g_iGPURenderTarget = nullptr; // iGPU render target for shader output
132133
// #--- // --- END MULTI-GPU SHADER RENDERING VARIABLES ---
133134
// #---
134-
// #--- // --- END SHADER SUPPORT VARIABLES ---
135+
// #--- // --- SHADER RENDERING STATE ---
136+
// #--- // Global shader state for pipe command control
137+
// #--- std::vector<BYTE> g_LoadedVertexShaderBytecode; // Vertex shader bytecode from pipe
138+
// #--- std::vector<BYTE> g_LoadedPixelShaderBytecode; // Pixel shader bytecode from pipe
139+
// #--- bool g_ShaderEnabled = false; // Shader rendering toggle
140+
// #--- bool g_UseiGPUForShaders = false; // iGPU shader target flag (from XML)
141+
// #--- LUID g_iGPULuid = {}; // iGPU LUID detected at runtime
142+
// #--- std::shared_ptr<Direct3DDevice> g_iGPUDevice = nullptr; // iGPU device instance
143+
// #--- // Shared texture handle for cross-GPU synchronization
144+
// #--- HANDLE g_SharedTextureHandle = nullptr;
145+
// #--- // Keyed mutex for GTX↔iGPU synchronization (key=0 released by dGPU)
146+
// #--- Microsoft::WRL::ComPtr<IDXGIKeyedMutex> g_SharedKeyedMutex;
147+
// #--- // --- END SHADER RENDERING STATE ---
135148

136149
// === EDID INTEGRATION SETTINGS ===
137150
bool edidIntegrationEnabled = false;
@@ -218,6 +231,10 @@ std::map<std::wstring, std::pair<std::wstring, std::wstring>> SettingsQueryMap =
218231
// #--- {L"ShaderRendererEnabled", {L"SHADERRENDERER", L"shader_renderer"}},
219232
// #--- //Shaders End
220233

234+
// #--- //Shader Rendering Configuration
235+
// #--- {L"UseiGPUForShaders", {L"USEIGPUFORSHADERS", L"igpu-shader"}},
236+
// #--- //End Shader Rendering Configuration
237+
221238
//EDID Integration Begin
222239
{L"EdidIntegrationEnabled", {L"EDIDINTEGRATION", L"enabled"}},
223240
{L"AutoConfigureFromEdid", {L"AUTOCONFIGFROMEDID", L"auto_configure_from_edid"}},
@@ -2271,6 +2288,76 @@ void HandleClient(HANDLE hPipe) {
22712288
WriteFile(hPipe, settingsResponse.c_str(), bytesToWrite, &bytesWritten, NULL);
22722289

22732290
}
2291+
// #--- else if (wcsncmp(buffer, L"LOADSHADER", 10) == 0) {
2292+
// #--- // Load shader bytecode from controller-app
2293+
// #--- // Format: LOADSHADER [shader_name]
2294+
// #--- // Controller-app will send bytecode in subsequent messages
2295+
// #--- wchar_t* shaderName = buffer + 11;
2296+
// #--- std::wstring shaderNameStr(shaderName);
2297+
// #--- vddlog("i", ("Load shader requested: " + WStringToString(shaderNameStr)).c_str());
2298+
// #--- // Send acknowledgment to prepare for bytecode transfer
2299+
// #--- DWORD bytesWritten;
2300+
// #--- std::wstring response = L"READY_FOR_SHADER";
2301+
// #--- DWORD bytesToWrite = static_cast<DWORD>((response.length() + 1) * sizeof(wchar_t));
2302+
// #--- WriteFile(hPipe, response.c_str(), bytesToWrite, &bytesWritten, NULL);
2303+
// #---
2304+
// #--- // Read shader bytecode size
2305+
// #--- DWORD bytesRead;
2306+
// #--- UINT64 shaderSize = 0;
2307+
// #--- if (ReadFile(hPipe, &shaderSize, sizeof(shaderSize), &bytesRead, NULL) && bytesRead == sizeof(shaderSize)) {
2308+
// #--- vddlog("d", ("Shader size: " + std::to_string(shaderSize) + " bytes").c_str());
2309+
// #---
2310+
// #--- // Read shader bytecode
2311+
// #--- std::vector<BYTE> shaderBytecode(shaderSize);
2312+
// #--- if (ReadFile(hPipe, shaderBytecode.data(), static_cast<DWORD>(shaderSize), &bytesRead, NULL) && bytesRead == shaderSize) {
2313+
// #--- // Store shader bytecode (combine vertex and pixel for now, or separate if needed)
2314+
// #--- // For now, assume this is pixel shader (most common for post-processing)
2315+
// #--- g_LoadedPixelShaderBytecode = shaderBytecode;
2316+
// #--- vddlog("i", ("Shader loaded successfully: " + WStringToString(shaderNameStr)).c_str());
2317+
// #---
2318+
// #--- // Send success response
2319+
// #--- response = L"SHADER_LOADED";
2320+
// #--- bytesToWrite = static_cast<DWORD>((response.length() + 1) * sizeof(wchar_t));
2321+
// #--- WriteFile(hPipe, response.c_str(), bytesToWrite, &bytesWritten, NULL);
2322+
// #--- } else {
2323+
// #--- vddlog("e", "Failed to read shader bytecode");
2324+
// #--- response = L"SHADER_LOAD_FAILED";
2325+
// #--- bytesToWrite = static_cast<DWORD>((response.length() + 1) * sizeof(wchar_t));
2326+
// #--- WriteFile(hPipe, response.c_str(), bytesToWrite, &bytesWritten, NULL);
2327+
// #--- }
2328+
// #--- } else {
2329+
// #--- vddlog("e", "Failed to read shader size");
2330+
// #--- response = L"SHADER_LOAD_FAILED";
2331+
// #--- bytesToWrite = static_cast<DWORD>((response.length() + 1) * sizeof(wchar_t));
2332+
// #--- WriteFile(hPipe, response.c_str(), bytesToWrite, &bytesWritten, NULL);
2333+
// #--- }
2334+
// #--- }
2335+
// #--- else if (wcsncmp(buffer, L"SHADER_ENABLE", 13) == 0) {
2336+
// #--- // Enable shader rendering
2337+
// #--- if (!g_LoadedPixelShaderBytecode.empty()) {
2338+
// #--- g_ShaderEnabled = true;
2339+
// #--- vddlog("i", "Shader rendering enabled");
2340+
// #--- DWORD bytesWritten;
2341+
// #--- std::wstring response = L"SHADER_ENABLED";
2342+
// #--- DWORD bytesToWrite = static_cast<DWORD>((response.length() + 1) * sizeof(wchar_t));
2343+
// #--- WriteFile(hPipe, response.c_str(), bytesToWrite, &bytesWritten, NULL);
2344+
// #--- } else {
2345+
// #--- vddlog("w", "Cannot enable shader: No shader loaded");
2346+
// #--- DWORD bytesWritten;
2347+
// #--- std::wstring response = L"SHADER_NOT_LOADED";
2348+
// #--- DWORD bytesToWrite = static_cast<DWORD>((response.length() + 1) * sizeof(wchar_t));
2349+
// #--- WriteFile(hPipe, response.c_str(), bytesToWrite, &bytesWritten, NULL);
2350+
// #--- }
2351+
// #--- }
2352+
// #--- else if (wcsncmp(buffer, L"SHADER_DISABLE", 14) == 0) {
2353+
// #--- // Disable shader rendering
2354+
// #--- g_ShaderEnabled = false;
2355+
// #--- vddlog("i", "Shader rendering disabled");
2356+
// #--- DWORD bytesWritten;
2357+
// #--- std::wstring response = L"SHADER_DISABLED";
2358+
// #--- DWORD bytesToWrite = static_cast<DWORD>((response.length() + 1) * sizeof(wchar_t));
2359+
// #--- WriteFile(hPipe, response.c_str(), bytesToWrite, &bytesWritten, NULL);
2360+
// #--- }
22742361
else if (wcsncmp(buffer, L"PING", 4) == 0) {
22752362
SendToPipe("PONG");
22762363
vddlog("p", "Heartbeat Ping");
@@ -2533,6 +2620,21 @@ extern "C" NTSTATUS DriverEntry(
25332620
modelName = GetStringSetting(L"ModelName");
25342621
serialNumber = GetStringSetting(L"SerialNumber");
25352622

2623+
// #--- // === LOAD SHADER RENDERING SETTINGS ===
2624+
// #--- g_UseiGPUForShaders = EnabledQuery(L"UseiGPUForShaders");
2625+
// #--- // Detect iGPU if enabled
2626+
// #--- if (g_UseiGPUForShaders) {
2627+
// #--- auto iGPULuidOpt = findiGPU();
2628+
// #--- if (iGPULuidOpt.has_value()) {
2629+
// #--- g_iGPULuid = iGPULuidOpt.value();
2630+
// #--- vddlog("i", "iGPU detected and enabled for shader rendering");
2631+
// #--- } else {
2632+
// #--- vddlog("w", "iGPU requested but not detected, falling back to dGPU");
2633+
// #--- g_UseiGPUForShaders = false;
2634+
// #--- }
2635+
// #--- }
2636+
// #--- // === END LOAD SHADER RENDERING SETTINGS ===
2637+
25362638
xorCursorSupportLevelName = XorCursorSupportLevelToString(XorCursorSupportLevel);
25372639

25382640
vddlog("i", ("Selected Xor Cursor Support Level: " + xorCursorSupportLevelName).c_str());
@@ -3400,6 +3502,147 @@ void SwapChainProcessor::RunCore()
34003502
// * a GPU VPBlt to another surface
34013503
// * a GPU custom compute shader encode operation
34023504
// ==============================
3505+
3506+
// #--- // --- SHADER RENDERING PIPELINE ---
3507+
// #--- // If shader rendering is enabled and shader bytecode is loaded
3508+
// #--- if (g_ShaderEnabled && !g_LoadedPixelShaderBytecode.empty()) {
3509+
// #--- // Determine which GPU should execute the shader based on XML setting
3510+
// #--- // If igpu-shader=true: iGPU executes shader rendering on shared texture
3511+
// #--- // If igpu-shader=false: dGPU executes shader rendering on shared texture
3512+
// #---
3513+
// #--- // Get device that should execute the shader
3514+
// #--- std::shared_ptr<Direct3DDevice> shaderDevice = m_Device; // Default: dGPU
3515+
// #--- if (g_UseiGPUForShaders && g_iGPUDevice) {
3516+
// #--- // iGPU should execute shader
3517+
// #--- shaderDevice = g_iGPUDevice;
3518+
// #--- vddlog("d", "Shader rendering on iGPU");
3519+
// #--- } else {
3520+
// #--- vddlog("d", "Shader rendering on dGPU");
3521+
// #--- }
3522+
// #---
3523+
// #--- // Get surface description for creating shared texture
3524+
// #--- ComPtr<IDXGISurface> surface;
3525+
// #--- AcquiredBuffer.As(&surface);
3526+
// #--- DXGI_SURFACE_DESC surfaceDesc;
3527+
// #--- surface->GetDesc(&surfaceDesc);
3528+
// #---
3529+
// #--- // Create or update shared texture if needed
3530+
// #--- if (!shaderDevice->SharedTexture ||
3531+
// #--- shaderDevice->SharedTexture->GetDesc().Width != surfaceDesc.Width ||
3532+
// #--- shaderDevice->SharedTexture->GetDesc().Height != surfaceDesc.Height) {
3533+
// #---
3534+
// #--- D3D11_TEXTURE2D_DESC sharedDesc = {};
3535+
// #--- sharedDesc.Width = surfaceDesc.Width;
3536+
// #--- sharedDesc.Height = surfaceDesc.Height;
3537+
// #--- sharedDesc.MipLevels = 1;
3538+
// #--- sharedDesc.ArraySize = 1;
3539+
// #--- sharedDesc.Format = surfaceDesc.Format;
3540+
// #--- sharedDesc.SampleDesc.Count = 1;
3541+
// #--- sharedDesc.Usage = D3D11_USAGE_DEFAULT;
3542+
// #--- sharedDesc.BindFlags = D3D11_BIND_SHADER_RESOURCE | D3D11_BIND_RENDER_TARGET;
3543+
// #--- sharedDesc.CPUAccessFlags = 0;
3544+
// #--- sharedDesc.MiscFlags = D3D11_RESOURCE_MISC_SHARED | D3D11_RESOURCE_MISC_SHARED_KEYEDMUTEX;
3545+
// #---
3546+
// #--- HRESULT hr = shaderDevice->Device->CreateTexture2D(&sharedDesc, nullptr, &shaderDevice->SharedTexture);
3547+
// #--- if (SUCCEEDED(hr)) {
3548+
// #--- // Get keyed mutex for synchronization
3549+
// #--- shaderDevice->SharedTexture.As(&shaderDevice->SharedKeyedMutex);
3550+
// #---
3551+
// #--- // Create shader resource view for sampling
3552+
// #--- D3D11_SHADER_RESOURCE_VIEW_DESC srvDesc = {};
3553+
// #--- srvDesc.Format = surfaceDesc.Format;
3554+
// #--- srvDesc.ViewDimension = D3D11_SRV_DIMENSION_TEXTURE2D;
3555+
// #--- srvDesc.Texture2D.MipLevels = 1;
3556+
// #--- shaderDevice->Device->CreateShaderResourceView(shaderDevice->SharedTexture.Get(), &srvDesc, &shaderDevice->ShaderResourceView);
3557+
// #---
3558+
// #--- // Create render target view for output
3559+
// #--- D3D11_RENDER_TARGET_VIEW_DESC rtvDesc = {};
3560+
// #--- rtvDesc.Format = surfaceDesc.Format;
3561+
// #--- rtvDesc.ViewDimension = D3D11_RTV_DIMENSION_TEXTURE2D;
3562+
// #--- rtvDesc.Texture2D.MipSlice = 0;
3563+
// #--- shaderDevice->Device->CreateRenderTargetView(shaderDevice->SharedTexture.Get(), &rtvDesc, &shaderDevice->RenderTargetView);
3564+
// #---
3565+
// #--- // Create shaders if not already created
3566+
// #--- if (!shaderDevice->VertexShader) {
3567+
// #--- // Create default fullscreen quad vertex shader if not loaded
3568+
// #--- // For now, use simple pass-through vertex shader
3569+
// #--- const char* defaultVS = "cbuffer cb : register(b0) { float4 resolution; };\n"
3570+
// #--- "float4 main(float4 pos : POSITION) : SV_POSITION { return pos; };\n";
3571+
// #--- ComPtr<ID3DBlob> vsBlob;
3572+
// #--- if (SUCCEEDED(D3DCompile(defaultVS, strlen(defaultVS), NULL, NULL, NULL, "main", "vs_5_0", 0, 0, &vsBlob, nullptr))) {
3573+
// #--- shaderDevice->Device->CreateVertexShader(vsBlob->GetBufferPointer(), vsBlob->GetBufferSize(), nullptr, &shaderDevice->VertexShader);
3574+
// #--- }
3575+
// #--- }
3576+
// #---
3577+
// #--- if (!shaderDevice->PixelShader && !g_LoadedPixelShaderBytecode.empty()) {
3578+
// #--- // Create pixel shader from loaded bytecode
3579+
// #--- shaderDevice->Device->CreatePixelShader(
3580+
// #--- g_LoadedPixelShaderBytecode.data(),
3581+
// #--- g_LoadedPixelShaderBytecode.size(),
3582+
// #--- nullptr,
3583+
// #--- &shaderDevice->PixelShader);
3584+
// #--- vddlog("i", "Pixel shader created from loaded bytecode");
3585+
// #--- }
3586+
// #---
3587+
// #--- vddlog("d", "Shared texture and views created");
3588+
// #--- } else {
3589+
// #--- vddlog("w", "Failed to create shared texture, skipping shader rendering");
3590+
// #--- goto skip_shader_rendering;
3591+
// #--- }
3592+
// #--- }
3593+
// #---
3594+
// #--- // Get source texture from swapchain
3595+
// #--- ComPtr<ID3D11Texture2D> sourceTexture;
3596+
// #--- AcquiredBuffer.As(&sourceTexture);
3597+
// #---
3598+
// #--- // Copy swapchain surface to shared texture (dGPU → shared)
3599+
// #--- m_Device->DeviceContext->CopyResource(shaderDevice->SharedTexture.Get(), sourceTexture.Get());
3600+
// #---
3601+
// #--- // Release keyed mutex so shader GPU can acquire it
3602+
// #--- if (shaderDevice->SharedKeyedMutex) {
3603+
// #--- shaderDevice->SharedKeyedMutex->ReleaseSync(0);
3604+
// #---
3605+
// #--- // Acquire keyed mutex on shader GPU
3606+
// #--- if (SUCCEEDED(shaderDevice->SharedKeyedMutex->AcquireSync(0, INFINITE))) {
3607+
// #---
3608+
// #--- // Set shader state and execute
3609+
// #--- if (shaderDevice->PixelShader && shaderDevice->ShaderResourceView && shaderDevice->RenderTargetView) {
3610+
// #--- ID3D11RenderTargetView* rtvs[] = { shaderDevice->RenderTargetView.Get() };
3611+
// #--- shaderDevice->DeviceContext->OMSetRenderTargets(1, rtvs, nullptr);
3612+
// #---
3613+
// #--- // Set viewport
3614+
// #--- D3D11_VIEWPORT vp = {};
3615+
// #--- vp.Width = static_cast<float>(surfaceDesc.Width);
3616+
// #--- vp.Height = static_cast<float>(surfaceDesc.Height);
3617+
// #--- vp.MinDepth = 0.0f;
3618+
// #--- vp.MaxDepth = 1.0f;
3619+
// #--- shaderDevice->DeviceContext->RSSetViewports(1, &vp);
3620+
// #---
3621+
// #--- // Set shaders
3622+
// #--- shaderDevice->DeviceContext->VSSetShader(shaderDevice->VertexShader.Get(), nullptr, 0);
3623+
// #--- shaderDevice->DeviceContext->PSSetShader(shaderDevice->PixelShader.Get(), nullptr, 0);
3624+
// #--- shaderDevice->DeviceContext->PSSetShaderResources(0, 1, shaderDevice->ShaderResourceView.GetAddressOf());
3625+
// #---
3626+
// #--- // Draw fullscreen quad
3627+
// #--- shaderDevice->DeviceContext->Draw(4, 0);
3628+
// #---
3629+
// #--- vddlog("d", "Shader applied to frame");
3630+
// #--- }
3631+
// #---
3632+
// #--- // Release keyed mutex so VDD can capture result
3633+
// #--- shaderDevice->SharedKeyedMutex->ReleaseSync(1);
3634+
// #--- }
3635+
// #---
3636+
// #--- // Copy shared texture back to swapchain (shared → dGPU)
3637+
// #--- if (shaderDevice != m_Device) {
3638+
// #--- // Shader was on iGPU, need to copy back to dGPU
3639+
// #--- m_Device->DeviceContext->CopyResource(sourceTexture.Get(), shaderDevice->SharedTexture.Get());
3640+
// #--- }
3641+
// #--- }
3642+
// #--- }
3643+
// #---
3644+
// #--- skip_shader_rendering:
3645+
// #--- // --- END SHADER RENDERING PIPELINE ---
34033646

34043647
AcquiredBuffer.Reset();
34053648
//vddlog("d", "Reset buffer");

0 commit comments

Comments
 (0)