VL.Stride.DX12Bridge
0.5.0-pre8
dotnet add package VL.Stride.DX12Bridge --version 0.5.0-pre8
NuGet\Install-Package VL.Stride.DX12Bridge -Version 0.5.0-pre8
<PackageReference Include="VL.Stride.DX12Bridge" Version="0.5.0-pre8" />
<PackageVersion Include="VL.Stride.DX12Bridge" Version="0.5.0-pre8" />
<PackageReference Include="VL.Stride.DX12Bridge" />
paket add VL.Stride.DX12Bridge --version 0.5.0-pre8
#r "nuget: VL.Stride.DX12Bridge, 0.5.0-pre8"
#:package VL.Stride.DX12Bridge@0.5.0-pre8
#addin nuget:?package=VL.Stride.DX12Bridge&version=0.5.0-pre8&prerelease
#tool nuget:?package=VL.Stride.DX12Bridge&version=0.5.0-pre8&prerelease
VL.Stride.DX12Bridge
High-performance DX11↔DX12 bridge for vvvv/Stride enabling mesh shaders, ray tracing, async compute, and Streamline/DLSS integration.
Overview
This library enables running D3D12 workloads alongside Stride's D3D11 rendering pipeline in vvvv gamma. It creates a secondary Stride GraphicsDevice with D3D12 backend on the same GPU adapter, allowing zero-copy texture sharing and GPU-side synchronization.
Features
- Zero-copy texture sharing via NTHANDLE between D3D11 and D3D12
- GPU-side fence synchronization - no CPU blocking
- Two-tier API:
- High-level: Use Stride's
CommandList,PipelineState(API-agnostic) - Low-level: Direct
ID3D12GraphicsCommandListaccess for DX12-exclusive features
- High-level: Use Stride's
- Per-app singleton via vvvv's ServiceRegistry pattern
- IGraphicsRendererBase integration for mid-frame D3D12 work
DX12-Exclusive Features
| Feature | DX11 | DX12 | Benefit |
|---|---|---|---|
| Mesh Shaders | ❌ | ✅ | GPU-driven culling, meshlet processing |
| Amplification Shaders | ❌ | ✅ | Dynamic LOD, replace tessellation |
| Async Compute | ❌ | ✅ | Overlap compute with graphics |
| Work Graphs | ❌ | ✅ | GPU-driven dispatch scheduling |
| Ray Tracing (DXR) | ❌ | ✅ | Hardware-accelerated ray tracing |
| Variable Rate Shading | ❌ | ✅ | Per-region shading rates |
| Sampler Feedback | ❌ | ✅ | Texture streaming optimization |
Architecture
┌─────────────────────────────────────────────────────────────────────────┐
│ vvvv AppHost (per application) │
│ ┌────────────────────────────────────────────────────────────────────┐ │
│ │ ServiceRegistry │ │
│ │ ├─ IResourceProvider<Game> → VLGame instance │ │
│ │ ├─ IResourceProvider<GraphicsDevice> → D3D11 Device │ │
│ │ └─ IResourceProvider<DX12BridgeService> → D3D12 Bridge ★ │ │
│ └────────────────────────────────────────────────────────────────────┘ │
└─────────────────────────────────────────────────────────────────────────┘
│
▼
┌─────────────────────────────────────────────────────────────────────────┐
│ DX12BridgeService (Singleton) │
│ ┌─────────────────────┬─────────────────────┬────────────────────────┐ │
│ │ D3D11Device │ D3D12Device │ D3D12Context │ │
│ │ (from Game) │ (same adapter) │ (command submission) │ │
│ ├─────────────────────┼─────────────────────┼────────────────────────┤ │
│ │ SharedTextures │ Sync │ NativeDevice │ │
│ │ (TexturePool) │ (FenceSynchronizer) │ (low-level access) │ │
│ └─────────────────────┴─────────────────────┴────────────────────────┘ │
└─────────────────────────────────────────────────────────────────────────┘
Usage
Getting the Bridge Service
// In vvvv/VL context
var bridge = AppHost.Current.Services.GetDX12Bridge();
// In Stride renderer context
var bridge = context.RenderContext.Services.GetService<DX12BridgeService>();
High-Level API (Stride Patterns)
Use Stride's familiar CommandList API - works identically to D3D11:
// Compute dispatch
var cmdList = bridge.D3D12Context.CommandList;
cmdList.SetPipelineState(computePSO);
cmdList.SetDescriptorSets(0, descriptorSets);
cmdList.Dispatch(128, 128, 1);
Low-Level API (Native D3D12)
For DX12-exclusive features like mesh shaders:
bridge.ExecuteNative(nativeCmdList =>
{
// Mesh shader dispatch (DX12-only)
var cmdList6 = nativeCmdList.QueryInterface<ID3D12GraphicsCommandList6>();
cmdList6.SetPipelineState(meshShaderPSO);
cmdList6.DispatchMesh(meshletCount, 1, 1);
});
Custom Renderer
Create a renderer that integrates with Stride's pipeline:
public class MyComputeRenderer : DX12ComputeRenderer
{
private PooledTexture? _colorInput;
private PooledTexture? _output;
protected override void PrepareInputs(RenderDrawContext context)
{
// Copy D3D11 texture to shared pool
_colorInput = Bridge.SharedTextures.PrepareInput(inputTexture, "Color");
_output = Bridge.SharedTextures.EnsureOutput(width, height, format, "Output");
}
protected override void ExecuteD3D12Work(GraphicsContext d3d12Context)
{
var cmdList = d3d12Context.CommandList;
cmdList.SetPipelineState(_computePSO);
// Bind _colorInput.D3D12Texture as SRV
// Bind _output.D3D12Texture as UAV
cmdList.Dispatch(width / 8, height / 8, 1);
}
protected override void CopyOutputs(RenderDrawContext context)
{
// Output is in shared texture, D3D11 can read it directly
OutputTexture = _output!.D3D11Texture;
}
}
Texture Sharing
How It Works
- D3D11 creates textures with
TextureOptions.SharedNthandle - D3D12 opens the same GPU memory via the shared handle
- Both APIs read/write the same physical texture
- Fence synchronization ensures correct ordering
Skip-Copy Optimization
The TexturePool tracks which textures were copied each frame. If the same source texture is requested twice in one frame, the GPU copy is skipped:
// First call: copies texture to pool
var pooled1 = pool.PrepareInput(sourceTexture, "Color");
// Second call same frame: returns cached, no copy
var pooled2 = pool.PrepareInput(sourceTexture, "Color");
Synchronization
GPU Fence Synchronization
Cross-API synchronization uses shared fences (~0.05ms, GPU-side):
// After D3D11 writes to shared texture
sync.SyncD3D11ToD3D12(); // D3D12 waits for D3D11
// Execute D3D12 work...
// After D3D12 writes to shared texture
sync.SyncD3D12ToD3D11(); // D3D11 waits for D3D12
Automatic Sync in DX12ComputeRenderer
The base class handles synchronization automatically. Override SyncBeforeExecute and SyncAfterExecute to customize:
protected override bool SyncBeforeExecute => true; // Default
protected override bool SyncAfterExecute => true; // Default
Performance Considerations
| Operation | Cost | Notes |
|---|---|---|
| Fence signal/wait | ~0.05ms | GPU-side, non-blocking |
| CopyResource | ~0.1ms | GPU data copy (color, D32 depth) |
| Depth D24→R32 | ~0.2ms | Shader conversion (format mismatch) |
| OpenSharedTexture | ~0 | Pointer only, no data copy |
Best Practices
- Minimize sync points - Batch multiple operations between syncs
- Use skip-copy optimization - Same source texture reuses cached data
- Prefer shared handles - Zero-copy when D3D11 textures have SharedNthandle
- Batch barriers - D3D12 resource barriers are batched automatically
Files
| File | Purpose |
|---|---|
Initialization.cs |
Service registration (per-app singleton) |
DX12BridgeService.cs |
Main singleton with two-tier API |
TexturePool.cs |
Shared texture management |
FenceSynchronizer.cs |
Cross-API GPU sync |
DX12ComputeRenderer.cs |
Base renderer class |
Requirements
- Windows 10 1703+ (for shared fences via ID3D11Device5)
- NVIDIA, AMD, or Intel GPU with D3D12 support
- Stride 4.2+
- vvvv gamma 2025.7+
Installation
Install via commandline as described here:
nuget install VL.Stride.DX12Bridge
Integration with VL.Nvidia.Streamline
This bridge is used by VL.Nvidia.Streamline for DLSS and frame generation. The Streamline SDK requires D3D12, and this bridge provides the infrastructure for texture sharing and synchronization between Stride's D3D11 rendering and Streamline's D3D12 operations.
Contributing
- Report issues on the vvvv forum
- See contributing guidelines
License
Free for personal, non-commercial use. © 2026 Tebjan Halm — see LICENSE.txt for full terms.
All other use (companies, studios, universities, research institutions, NGOs, government bodies, freelancers) requires a commercial license from Tebjan Halm — contact via tebjan@gmail.com or tebjan.de.
| Product | Versions Compatible and additional computed target framework versions. |
|---|---|
| .NET Framework | net is compatible. |
-
net8.0-windows7.0
- Silk.NET.Direct3D.Compilers (>= 2.22.0)
- Silk.NET.Direct3D11 (>= 2.22.0)
- Silk.NET.Direct3D12 (>= 2.22.0)
NuGet packages (3)
Showing the top 3 NuGet packages that depend on VL.Stride.DX12Bridge:
| Package | Downloads |
|---|---|
|
VL.Nvidia.PathTracing
SOTA real-time path tracing for vvvv gamma with NRD denoising, ReSTIR sampling, and DLSS integration. |
|
|
VL.Nvidia.Streamline
NVIDIA Streamline integration for vvvv gamma. |
|
|
VL.Pathtracing
SOTA real-time path tracing for vvvv gamma with NRD denoising, ReSTIR sampling, and DLSS integration. |
GitHub repositories
This package is not used by any popular GitHub repositories.
| Version | Downloads | Last Updated |
|---|---|---|
| 0.5.0-pre8 | 91 | 4/28/2026 |
| 0.5.0-pre7 | 66 | 4/28/2026 |
| 0.5.0-pre6 | 61 | 4/28/2026 |
| 0.5.0-pre5 | 57 | 4/28/2026 |
| 0.5.0-pre4 | 62 | 4/28/2026 |
| 0.5.0-pre3 | 60 | 4/27/2026 |
| 0.5.0-pre2 | 57 | 4/27/2026 |
| 0.5.0-pre1 | 83 | 4/27/2026 |