VL.Stride.DX12Bridge 0.5.0-pre8

This is a prerelease version of VL.Stride.DX12Bridge.
dotnet add package VL.Stride.DX12Bridge --version 0.5.0-pre8
                    
NuGet\Install-Package VL.Stride.DX12Bridge -Version 0.5.0-pre8
                    
This command is intended to be used within the Package Manager Console in Visual Studio, as it uses the NuGet module's version of Install-Package.
<PackageReference Include="VL.Stride.DX12Bridge" Version="0.5.0-pre8" />
                    
For projects that support PackageReference, copy this XML node into the project file to reference the package.
<PackageVersion Include="VL.Stride.DX12Bridge" Version="0.5.0-pre8" />
                    
Directory.Packages.props
<PackageReference Include="VL.Stride.DX12Bridge" />
                    
Project file
For projects that support Central Package Management (CPM), copy this XML node into the solution Directory.Packages.props file to version the package.
paket add VL.Stride.DX12Bridge --version 0.5.0-pre8
                    
#r "nuget: VL.Stride.DX12Bridge, 0.5.0-pre8"
                    
#r directive can be used in F# Interactive and Polyglot Notebooks. Copy this into the interactive tool or source code of the script to reference the package.
#:package VL.Stride.DX12Bridge@0.5.0-pre8
                    
#:package directive can be used in C# file-based apps starting in .NET 10 preview 4. Copy this into a .cs file before any lines of code to reference the package.
#addin nuget:?package=VL.Stride.DX12Bridge&version=0.5.0-pre8&prerelease
                    
Install as a Cake Addin
#tool nuget:?package=VL.Stride.DX12Bridge&version=0.5.0-pre8&prerelease
                    
Install as a Cake Tool

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 ID3D12GraphicsCommandList access for DX12-exclusive features
  • 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

  1. D3D11 creates textures with TextureOptions.SharedNthandle
  2. D3D12 opens the same GPU memory via the shared handle
  3. Both APIs read/write the same physical texture
  4. 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

  1. Minimize sync points - Batch multiple operations between syncs
  2. Use skip-copy optimization - Same source texture reuses cached data
  3. Prefer shared handles - Zero-copy when D3D11 textures have SharedNthandle
  4. 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

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 Compatible and additional computed target framework versions.
.NET Framework net is compatible. 
Compatible target framework(s)
Included target framework(s) (in package)
Learn more about Target Frameworks and .NET Standard.

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