Skip to main content

Repository Overview

The Virtual Display Driver repository contains multiple components organized into logical directories.
Virtual-Display-Driver/
├── Virtual Display Driver (HDR)/  # Main driver (IddCx 1.10)
├── Virtual-Audio-Driver/          # Companion audio driver
├── Common/                        # Shared headers and utilities
├── ThirdParty/                    # External dependencies
├── Community Scripts/             # User-contributed utilities
├── scripts/                       # Build and deployment scripts
└── .github/                       # GitHub workflows and templates

Main Driver Directory

Virtual Display Driver (HDR)

The primary driver implementation using IddCx 1.10 with HDR support.
Virtual Display Driver (HDR)/
├── MttVDD/                 # Driver project
│   ├── Driver.cpp          # Main driver implementation (5000+ lines)
│   ├── Driver.h            # Driver header and class definitions
│   ├── Trace.h             # WPP tracing configuration
│   ├── MttVDD.inf          # Driver installation file
│   ├── MttVDD.vcxproj      # Visual Studio project file
│   └── MttVDD.sln          # Solution file
├── EDID/                   # EDID profile binaries
├── GetIddCx/               # IddCx version query utility
├── vdd_settings.xml        # Default driver configuration
├── option.txt              # Legacy configuration file
└── MttVDD.sln              # Root solution file

Key Source Files

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

The main driver implementation file containing: Size: ~5,000 lines of C++17 code Key Components:

1. Driver Entry and Initialization

// Driver entry point - called when driver loads
extern "C" DRIVER_INITIALIZE DriverEntry;

// Device context initialization
IndirectDeviceContext::IndirectDeviceContext(_In_ WDFDEVICE WdfDevice)
Functions:
  • DriverEntry() - Driver initialization entry point
  • InitAdapter() - Initialize IddCx adapter
  • FinishInit() - Complete driver initialization

2. Monitor Management

void IndirectDeviceContext::CreateMonitor(unsigned int index)
Responsibilities:
  • Create virtual monitor instances
  • Configure display modes and capabilities
  • Load EDID profiles
  • Handle monitor arrival/removal events

3. SwapChain Processing

class SwapChainProcessor
{
    DWORD CALLBACK RunThread(LPVOID Argument);
    void RunCore();
};
Responsibilities:
  • Process frame buffers from applications
  • Manage frame presentation timing
  • Handle buffer synchronization
  • Coordinate with GPU rendering

4. Direct3D Device Management

struct Direct3DDevice
{
    Direct3DDevice(LUID AdapterLuid);
    HRESULT Init();
};
Responsibilities:
  • Create and manage D3D11 devices
  • Handle GPU adapter selection
  • Cache devices for performance
  • Support multi-GPU configurations

5. Configuration Parsing

XML Configuration Handling:
  • Parse vdd_settings.xml
  • Apply monitor configurations
  • Handle EDID profile loading
  • Manage GPU adapter preferences

6. Phase 5 Integration Functions

NTSTATUS ValidateEdidIntegration();
NTSTATUS PerformanceMonitor();
NTSTATUS CreateFallbackConfiguration();
NTSTATUS ValidateAndSanitizeConfiguration();
NTSTATUS RunComprehensiveDiagnostics();
NTSTATUS InitializePhase5Integration();
Advanced features for validation and diagnostics.

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

Header file with class definitions and declarations: Key Classes:
namespace Microsoft::IndirectDisp {
    // Direct3D device manager
    struct Direct3DDevice {
        LUID AdapterLuid;
        ComPtr<IDXGIFactory5> DxgiFactory;
        ComPtr<IDXGIAdapter1> Adapter;
        ComPtr<ID3D11Device> Device;
        ComPtr<ID3D11DeviceContext> DeviceContext;
    };
    
    // SwapChain frame processor
    class SwapChainProcessor {
        IDDCX_SWAPCHAIN m_hSwapChain;
        std::shared_ptr<Direct3DDevice> m_Device;
        HANDLE m_hAvailableBufferEvent;
        Microsoft::WRL::Wrappers::Thread m_hThread;
    };
    
    // Main driver context
    class IndirectDeviceContext {
        WDFDEVICE m_WdfDevice;
        IDDCX_ADAPTER m_Adapter;
        IDDCX_MONITOR m_Monitor;
        IDDCX_MONITOR m_Monitor2;
        std::unique_ptr<SwapChainProcessor> m_ProcessingThread;
    };
}
Utility Functions:
std::vector<std::string> split(std::string& input, char delimiter);
std::string WStringToString(const std::wstring& wstr);

Trace.h (Virtual Display Driver (HDR)/MttVDD/Trace.h)

Windows Performance Toolkit (WPP) tracing configuration:
// Tracing GUID and configuration
// Enables diagnostic logging via ETW
Usage in code:
TraceEvents(TRACE_LEVEL_INFORMATION, TRACE_DRIVER, "Monitor created");
TraceEvents(TRACE_LEVEL_ERROR, TRACE_DRIVER, "Failed: 0x%x", status);

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

Driver installation file defining: Sections:
  • [Version] - Driver metadata and signature
  • [Manufacturer] - Manufacturer information
  • [Standard.NT$ARCH$] - Hardware IDs (Root\MttVDD)
  • [MyDevice_Install.NT] - Installation instructions
  • [MyDevice_HardwareDeviceSettings] - Registry settings
  • [MttVDD_Install] - UMDF service configuration
Key Settings:
UmdfLibraryVersion = $UMDFVERSION$
ServiceBinary = %12%\UMDF\MttVDD.dll
UmdfExtensions = IddCx0102
HKR,, "UpperFilters", %REG_MULTI_SZ%, "IndirectKmd"

Common Headers

AdapterOption.h (Common/Include/AdapterOption.h)

GPU adapter selection and management: Key Components:
struct GPUInfo {
    wstring name;
    ComPtr<IDXGIAdapter> adapter;
    DXGI_ADAPTER_DESC desc;
};

class AdapterOption {
    bool hasTargetAdapter;
    LUID adapterLuid;
    wstring target_name;
    
    wstring selectBestGPU();
    void load(const wchar_t* path);
    void xmlprovide(const wstring& xtarg);
    void apply(const IDDCX_ADAPTER& adapter);
};
Features:
  • Enumerate available GPUs via DXGI
  • Select adapter by name or PCI bus number
  • Resolve adapter LUID from PCI bus (more deterministic)
  • Automatic fallback to best GPU (most VRAM)
  • Integration with vdd_settings.xml
PCI Bus Resolution:
std::optional<LUID> ResolveAdapterLuidFromPciBus(uint32_t targetBusIndex);
Allows specifying GPU as “GPU Name,Bus” for multi-GPU systems.

Configuration Files

vdd_settings.xml (Virtual Display Driver (HDR)/vdd_settings.xml)

Runtime configuration file defining: Structure (example):
<VirtualDisplayDriver>
  <Monitors>
    <Monitor id="0">
      <Enabled>true</Enabled>
      <Resolution>1920x1080</Resolution>
      <RefreshRate>60</RefreshRate>
      <EDID>path/to/edid.bin</EDID>
    </Monitor>
  </Monitors>
  <Adapter>
    <TargetGPU>NVIDIA GeForce RTX 3080</TargetGPU>
  </Adapter>
</VirtualDisplayDriver>
Copied to: C:\VirtualDisplayDriver\vdd_settings.xml on installation

option.txt (Virtual Display Driver (HDR)/option.txt)

Legacy configuration file (pre-XML):
  • Simple text file
  • GPU adapter name on first line
  • Maintained for backward compatibility

EDID Profiles

EDID Directory (Virtual Display Driver (HDR)/EDID/)

Contains binary EDID files for different display profiles: Purpose:
  • Define monitor capabilities (resolutions, color spaces, HDR)
  • Emulate specific hardware displays
  • Custom display naming and manufacturer info
Usage:
// Load EDID from file
std::vector<BYTE> s_KnownMonitorEdid = ReadEdidFromFile("EDID/profile.bin");

Utility Components

GetIddCx (Virtual Display Driver (HDR)/GetIddCx/)

Utility to query installed IddCx version: Source: IddCxVersionQuery.cpp Purpose:
  • Detect IddCx version on system
  • Verify driver compatibility
  • Debugging and support
Usage:
GetIddCx.exe
# Output: IddCx version 1.10.0.0

Third-Party Dependencies

Windows-Driver-Frameworks (ThirdParty/Windows-Driver-Frameworks/)

Contains:
  • UMDF 2.15 public headers
  • Additional WDF header files not in standard WDK
Include Path:
$(ProjectDir)..\..\ThirdParty\Windows-Driver-Frameworks\src\publicinc\wdf\umdf\2.15

Community Scripts

Community Scripts/ Directory

User-contributed PowerShell scripts: Common Scripts:
  • Monitor creation and removal
  • Batch configuration
  • Display settings automation
  • EDID generation helpers
See Community Scripts README.

Build Scripts

scripts/ Directory

Build and deployment automation:
  • CI/CD scripts
  • Release packaging
  • Automated testing

GitHub Configuration

.github/ Directory

workflows/:
  • GitHub Actions CI/CD pipelines
  • Automated builds
  • Release creation
ISSUE_TEMPLATE/:
  • bug_report.yml - Bug report template
  • feature_request.yml - Feature request template
  • Question.yml - Question template
  • HelpWanted.yml - Help wanted template
FUNDING.yml:
  • Sponsor links for project maintainers

Code Flow Overview

Driver Initialization Flow

1. DriverEntry()
   └─> Create WDFDRIVER object
       └─> Set device callbacks

2. DeviceAdd callback
   └─> Create IndirectDeviceContext
       └─> InitAdapter()
           ├─> Create IDDCX_ADAPTER
           ├─> Load configuration (vdd_settings.xml)
           ├─> Apply GPU adapter settings
           └─> IddCxAdapterInitAsync()

3. AdapterInit callback
   └─> FinishInit()
       └─> CreateMonitor(0), CreateMonitor(1), ...
           ├─> Load EDID profile
           ├─> Configure display modes
           └─> IddCxMonitorArrival()

Frame Processing Flow

1. Application renders to virtual display
   └─> IddCx provides IDDCX_SWAPCHAIN

2. SwapChain assigned to monitor
   └─> AssignSwapChain()
       └─> Create SwapChainProcessor
           └─> Start processing thread

3. SwapChainProcessor::RunCore()
   └─> Loop:
       ├─> IddCxSwapChainReleaseAndAcquireBuffer()
       ├─> Process frame (if needed)
       └─> IddCxSwapChainFinishedProcessingFrame()

Architecture Patterns

Device Caching

Direct3D devices are cached per LUID:
static std::map<LUID, std::shared_ptr<Direct3DDevice>, LuidComparator> s_DeviceCache;
static std::mutex s_DeviceCacheMutex;
Benefits:
  • Avoid recreating D3D devices
  • Support multiple monitors on same GPU
  • Thread-safe access with mutex

LUID-Based GPU Selection

Older approach: Match by GPU name string Current approach: Match by PCI bus → resolve to LUID Advantages:
  • More deterministic in multi-GPU setups
  • Handles renamed/duplicate GPU names
  • Survives driver updates

WPP Tracing

Using WPP (Windows software trace preprocessor) instead of DbgPrint: Benefits:
  • Low overhead when not tracing
  • Rich structured logging
  • ETW (Event Tracing for Windows) integration
  • Production-safe diagnostics

Key Technologies

TechnologyPurposeLocation
IddCx 1.10Indirect display frameworkDriver.cpp, Windows SDK
UMDF 2.25User-mode driver frameworkEntire driver
Direct3D 11GPU rendering interfaceDirect3DDevice, SwapChainProcessor
DXGI 1.5Graphics infrastructureAdapter enumeration
WPP TracingDiagnostic loggingTrace.h, Driver.cpp
XMLLiteConfiguration parsingDriver.cpp
WRLCOM smart pointersThroughout (Microsoft::WRL::ComPtr)
STLC++ standard libraryvector, map, string, mutex

Next Steps

Building from Source

Compile the driver with your changes

Testing

Test your modifications safely

Additional Resources

Build docs developers (and LLMs) love