Documentation Index
Fetch the complete documentation index at: https://mintlify.com/VirtualDrivers/Virtual-Display-Driver/llms.txt
Use this file to discover all available pages before exploring further.
Overview
The Direct3DDevice struct encapsulates the creation and lifetime management of a Direct3D render device used for frame processing in the virtual display driver. It manages DXGI factory, adapter, D3D device, and device context objects.
Header: Driver.h:52-66
Implementation: Driver.cpp:2992-3076
Structure Declaration
struct Direct3DDevice
{
Direct3DDevice(LUID AdapterLuid);
Direct3DDevice();
HRESULT Init();
LUID AdapterLuid;
Microsoft::WRL::ComPtr<IDXGIFactory5> DxgiFactory;
Microsoft::WRL::ComPtr<IDXGIAdapter1> Adapter;
Microsoft::WRL::ComPtr<ID3D11Device> Device;
Microsoft::WRL::ComPtr<ID3D11DeviceContext> DeviceContext;
};
Constructors
Direct3DDevice(LUID AdapterLuid)
Signature:
Direct3DDevice::Direct3DDevice(LUID AdapterLuid);
Parameters:
AdapterLuid: Locally Unique Identifier for the target GPU adapter
Source Location: Driver.cpp:2992
Purpose: Initializes the device object with a specific GPU adapter LUID.
Usage:
LUID adapterLuid = {0x1234, 0x5678};
Direct3DDevice device(adapterLuid);
HRESULT hr = device.Init(); // Must call Init() after construction
Direct3DDevice()
Signature:
Direct3DDevice::Direct3DDevice();
Source Location: Driver.cpp:2996
Purpose: Initializes the device object with zeroed LUID (default adapter).
Usage:
Direct3DDevice device;
HRESULT hr = device.Init(); // Will use default GPU adapter
Initialization
Init
Signature:
HRESULT Direct3DDevice::Init();
Source Location: Driver.cpp:3000
Purpose: Initializes all Direct3D resources (factory, adapter, device, context).
Returns:
S_OK on success
- DXGI or D3D error code on failure
Initialization Steps:
1. Create DXGI Factory
hr = CreateDXGIFactory2(0, IID_PPV_ARGS(&DxgiFactory));
if (FAILED(hr)) {
vddlog("e", "Failed to create DXGI factory");
return hr;
}
Notes:
- Factory is not cached to detect new adapters appearing on the system
- Can check
DxgiFactory->IsCurrent() if caching is desired
- Re-create factory if
IsCurrent() returns false
2. Enumerate Adapter by LUID
hr = DxgiFactory->EnumAdapterByLuid(AdapterLuid, IID_PPV_ARGS(&Adapter));
if (FAILED(hr)) {
vddlog("e", "Failed to enumerate adapter by LUID");
return hr;
}
// Log adapter information
DXGI_ADAPTER_DESC desc;
Adapter->GetDesc(&desc);
vddlog("i", ("Adapter found: " + desc.Description).c_str());
Failure Scenarios:
- LUID not found (GPU removed, detached, or invalid LUID)
- GPU device disabled
- Driver not loaded
3. Create D3D11 Device
D3D_FEATURE_LEVEL featureLevels[] = {
D3D_FEATURE_LEVEL_11_1,
D3D_FEATURE_LEVEL_11_0
};
D3D_FEATURE_LEVEL featureLevel;
hr = D3D11CreateDevice(
Adapter.Get(), // Use specific adapter
D3D_DRIVER_TYPE_UNKNOWN, // Must be UNKNOWN when adapter specified
nullptr, // No software rasterizer
D3D11_CREATE_DEVICE_BGRA_SUPPORT, // Required by WHQL test suite
featureLevels,
ARRAYSIZE(featureLevels),
D3D11_SDK_VERSION,
&Device,
&featureLevel,
&DeviceContext
);
Feature Levels:
- D3D_FEATURE_LEVEL_11_1: Preferred, supports advanced features
- D3D_FEATURE_LEVEL_11_0: Fallback for older GPUs
Creation Flags:
D3D11_CREATE_DEVICE_BGRA_SUPPORT: Mandatory for IddCx drivers (WHQL requirement)
Failure Scenarios:
- GPU lost or removed (e.g., detachable eGPU)
- System in transient state (driver update, power transition)
- Out of memory
- Driver crash recovery
Error Handling:
if (FAILED(hr)) {
vddlog("e", "Failed to create Direct3D device");
vddlog("e", "GPU may be lost or system in transient state");
return hr;
}
Member Variables
AdapterLuid
Type: LUID
Purpose: Locally Unique Identifier for the GPU adapter.
Structure:
typedef struct _LUID {
DWORD LowPart;
LONG HighPart;
} LUID;
Usage:
LUID luid = device.AdapterLuid;
printf("Adapter LUID: %08X-%08X\n", luid.HighPart, luid.LowPart);
DxgiFactory
Type: Microsoft::WRL::ComPtr<IDXGIFactory5>
Purpose: DXGI factory for adapter enumeration and resource creation.
Capabilities:
- Enumerate display adapters
- Query adapter properties
- Create swap chains
- Check feature support
Version Support:
IDXGIFactory5: Windows 10 Creators Update (1703) and later
- Provides HDR and advanced color support
Adapter
Type: Microsoft::WRL::ComPtr<IDXGIAdapter1>
Purpose: Represents the physical GPU adapter.
Common Operations:
// Get adapter description
DXGI_ADAPTER_DESC1 desc;
device.Adapter->GetDesc1(&desc);
// Query video memory
printf("Dedicated Video Memory: %llu MB\n",
desc.DedicatedVideoMemory / (1024 * 1024));
// Check for software adapter
if (desc.Flags & DXGI_ADAPTER_FLAG_SOFTWARE) {
printf("Software adapter\n");
}
Device
Type: Microsoft::WRL::ComPtr<ID3D11Device>
Purpose: Main D3D11 device for resource creation and rendering.
Common Operations:
// Create resources
ID3D11Texture2D* texture;
device.Device->CreateTexture2D(&desc, nullptr, &texture);
// Create shader
ID3D11VertexShader* shader;
device.Device->CreateVertexShader(bytecode, size, nullptr, &shader);
// Check feature support
D3D11_FEATURE_DATA_D3D11_OPTIONS options;
device.Device->CheckFeatureSupport(
D3D11_FEATURE_D3D11_OPTIONS,
&options,
sizeof(options)
);
DeviceContext
Type: Microsoft::WRL::ComPtr<ID3D11DeviceContext>
Purpose: Immediate context for issuing rendering commands.
Common Operations:
// Copy resource
device.DeviceContext->CopyResource(pDest, pSrc);
// Draw
device.DeviceContext->Draw(vertexCount, 0);
// Map resource for CPU access
D3D11_MAPPED_SUBRESOURCE mapped;
device.DeviceContext->Map(resource, 0, D3D11_MAP_READ, 0, &mapped);
// ... access mapped.pData ...
device.DeviceContext->Unmap(resource, 0);
Device Caching
The driver implements device caching to reuse D3D devices across multiple monitors on the same GPU:
Cache Declaration:
static std::map<LUID, std::shared_ptr<Direct3DDevice>, LuidComparator> s_DeviceCache;
static std::mutex s_DeviceCacheMutex;
LUID Comparator:
struct LuidComparator {
bool operator()(const LUID& a, const LUID& b) const {
if (a.HighPart != b.HighPart)
return a.HighPart < b.HighPart;
return a.LowPart < b.LowPart;
}
};
Cache Access (Driver.h:137-138):
static std::shared_ptr<Direct3DDevice> GetOrCreateDevice(LUID RenderAdapter);
static void CleanupExpiredDevices();
GetOrCreateDevice
Purpose: Retrieves cached device or creates new one if not cached.
Thread Safety: Protected by s_DeviceCacheMutex.
Usage:
std::shared_ptr<Direct3DDevice> device =
IndirectDeviceContext::GetOrCreateDevice(renderAdapterLuid);
Benefits:
- Reduces device creation overhead
- Shares GPU resources across monitors
- Automatic reference counting
Error Recovery
Device Lost Handling
When GPU device is lost (removed, driver reset, power state change):
// Validate device before use
if (!m_Device || !m_Device->Device) {
vddlog("e", "Direct3DDevice became invalid");
return STATUS_UNSUCCESSFUL;
}
// Check for device removed
HRESULT hr = m_Device->Device->GetDeviceRemovedReason();
if (FAILED(hr)) {
vddlog("e", "Device removed");
// OS will trigger new swap chain with new device
return hr;
}
Transient State Recovery
For transient failures during initialization:
HRESULT hr = device.Init();
if (hr == DXGI_ERROR_DEVICE_REMOVED || hr == DXGI_ERROR_DEVICE_RESET) {
// Retry after delay
Sleep(100);
hr = device.Init();
}
Integration with SwapChainProcessor
The Direct3DDevice is used by SwapChainProcessor for frame processing:
class SwapChainProcessor {
std::shared_ptr<Direct3DDevice> m_Device;
public:
SwapChainProcessor(IDDCX_SWAPCHAIN hSwapChain,
std::shared_ptr<Direct3DDevice> Device,
HANDLE NewFrameEvent)
: m_Device(Device) {
// Set device to swap chain
ComPtr<IDXGIDevice> DxgiDevice;
m_Device->Device.As(&DxgiDevice);
IDARG_IN_SWAPCHAINSETDEVICE SetDevice = {};
SetDevice.pDevice = DxgiDevice.Get();
IddCxSwapChainSetDevice(hSwapChain, &SetDevice);
}
};
Factory Recreation
Current Implementation:
hr = CreateDXGIFactory2(0, IID_PPV_ARGS(&DxgiFactory));
Optimization Opportunity:
// Cache factory and check if current
if (cachedFactory && cachedFactory->IsCurrent()) {
DxgiFactory = cachedFactory;
} else {
hr = CreateDXGIFactory2(0, IID_PPV_ARGS(&DxgiFactory));
cachedFactory = DxgiFactory;
}
Trade-offs:
- Current: Always detects new adapters, slight overhead
- Cached: Better performance, may miss hot-plugged GPUs
BGRA Support Flag
The D3D11_CREATE_DEVICE_BGRA_SUPPORT flag is mandatory for IddCx drivers:
hr = D3D11CreateDevice(
Adapter.Get(),
D3D_DRIVER_TYPE_UNKNOWN,
nullptr,
D3D11_CREATE_DEVICE_BGRA_SUPPORT, // Required!
// ...
);
Reason: WHQL test suite requires BGRA surface support for compatibility.
Debugging
Debug Device Creation
For development builds, enable D3D debug layer:
UINT createDeviceFlags = D3D11_CREATE_DEVICE_BGRA_SUPPORT;
#ifdef _DEBUG
createDeviceFlags |= D3D11_CREATE_DEVICE_DEBUG;
#endif
hr = D3D11CreateDevice(
Adapter.Get(),
D3D_DRIVER_TYPE_UNKNOWN,
nullptr,
createDeviceFlags,
// ...
);
Logging
The implementation logs all major steps:
vddlog("d", "Initializing Direct3DDevice...");
vddlog("d", "DXGI factory created successfully");
vddlog("i", "Adapter found: [name]");
vddlog("i", "Direct3D device created successfully");
vddlog("e", "Failed to create Direct3D device");
References
- Source Files:
~/workspace/source/Virtual Display Driver (HDR)/MttVDD/Driver.h (lines 52-66)
~/workspace/source/Virtual Display Driver (HDR)/MttVDD/Driver.cpp (lines 2992-3076)
- Related Classes: SwapChainProcessor
- Microsoft Documentation: