vvvv-dotnet
.NET Integration in vvvv gamma
.csproj Configuration for vvvv Plugins
Minimal .csproj for a vvvv gamma C# plugin:
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>net8.0</TargetFramework>
<OutputPath Condition="'$(Configuration)'=='Release'">..\..\lib\net8.0\</OutputPath>
<AppendTargetFrameworkToOutputPath>false</AppendTargetFrameworkToOutputPath>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="VL.Core" Version="2025.7.*" />
<PackageReference Include="VL.Stride" Version="2025.7.*" />
</ItemGroup>
</Project>
Key settings:
- Target framework:
net8.0(required for vvvv gamma 6+) - Output path: Point to
lib/net8.0/relative to your.vldocument - AppendTargetFrameworkToOutputPath: Set to
falseso DLLs go directly to the output folder
How vvvv Uses C# Code
There are two workflows for integrating C# with a .vl document:
Source project reference (live reload): The .vl document references a .csproj. vvvv compiles .cs source files itself via Roslyn into in-memory assemblies — no dotnet build needed. On every .cs file save, vvvv detects the change and recompiles automatically. The output path in .csproj is not involved during live development; it is used for NuGet packaging and deployment.
Binary reference (no live reload): The .vl document references a pre-compiled DLL or NuGet package. To apply C# changes, rebuild externally (dotnet build) and restart vvvv. This is the standard workflow for larger projects and stable libraries.
Shaders (.sdsl files) always live-reload regardless of workflow.
For AI agents: regardless of workflow, run dotnet build to verify your code compiles — you cannot see vvvv's compiler output. For source project references, vvvv picks up changes on file save automatically (no restart needed). For binary references, dotnet build is required and the user must restart vvvv.
Required Global Usings
global using VL.Core;
global using VL.Core.Import;
global using VL.Lib.Collections;
Required Assembly Attribute
For vvvv to discover your ProcessNodes and static methods:
[assembly: ImportAsIs]
Without this, your nodes will not appear in the vvvv node browser.
NuGet Package Sources
Add these to your NuGet.config for vvvv packages:
<configuration>
<packageSources>
<add key="nuget.org" value="https://api.nuget.org/v3/index.json" />
<add key="vvvv" value="https://teamcity.vvvv.org/guestAuth/app/nuget/v1/FeedService.svc/" />
</packageSources>
</configuration>
NuGet Packaging
To distribute your plugin as a NuGet package:
nuget pack MyPlugin/deployment/MyPlugin.nuspec
The .nuspec should reference your .vl document, compiled DLLs, shader files, and help patches.
Common VL Packages
| Package | Purpose |
|---|---|
VL.Core |
Core types, ProcessNode attribute, Spread |
VL.Stride |
3D rendering, shader integration |
VL.Stride.Runtime |
Stride engine runtime |
VL.Core.Import |
ImportAsIs attribute |
VL.Lib.Collections |
Spread, SpreadBuilder |
VL.Skia |
2D rendering (Skia graphics engine) |
VL.Fuse |
GPU visual programming (shader graph) |
VL.IO.OSC |
Open Sound Control protocol |
VL.IO.MQTT |
MQTT messaging |
VL.IO.Redis |
Redis key-value store |
VL.OpenCV |
Computer vision (OpenCV bindings) |
VL.MediaPipe |
MediaPipe ML pipelines (hand, face, pose) |
VL.Audio |
Audio synthesis and I/O (NAudio-based) |
VL.Devices.AzureKinect |
Azure Kinect / Orbbec depth cameras |
For a full catalog, see vvvv.org/packs.
Vector Types & SIMD Strategy
- Internal hot paths: Use
System.Numerics.Vector3/Vector4/Quaternion(SIMD via AVX/SSE) - External API (Update method params): Use
Stride.Core.Mathematicstypes (required by VL) - Zero-cost conversion between them:
using System.Runtime.CompilerServices;
// Stride → System.Numerics (zero-cost reinterpret)
ref var numericsVec = ref Unsafe.As<Stride.Core.Mathematics.Vector3, System.Numerics.Vector3>(ref strideVec);
// System.Numerics → Stride (zero-cost reinterpret)
ref var strideVec = ref Unsafe.As<System.Numerics.Vector3, Stride.Core.Mathematics.Vector3>(ref numericsVec);
These types have identical memory layouts, making Unsafe.As a zero-cost operation.
IDisposable and Resource Management
Any node holding native/unmanaged resources must implement IDisposable:
[ProcessNode]
public class NativeWrapper : IDisposable
{
private IntPtr _handle;
public NativeWrapper()
{
_handle = NativeLib.Create();
}
public void Update(out int result)
{
result = NativeLib.Process(_handle);
}
public void Dispose()
{
if (_handle != IntPtr.Zero)
{
NativeLib.Destroy(_handle);
_handle = IntPtr.Zero;
}
}
}
vvvv calls Dispose() when the node is removed or the document closes.
Async Patterns in vvvv
Since Update() runs on the main thread at 60 FPS, long-running operations must be async:
[ProcessNode]
public class AsyncLoader
{
private Task<string>? _loadTask;
private string _cachedResult = "";
public void Update(
out string result,
out bool isLoading,
string url = "",
bool trigger = false)
{
if (trigger && (_loadTask == null || _loadTask.IsCompleted))
{
_loadTask = Task.Run(() => LoadFromUrl(url));
}
isLoading = _loadTask != null && !_loadTask.IsCompleted;
if (_loadTask?.IsCompletedSuccessfully == true)
_cachedResult = _loadTask.Result;
result = _cachedResult;
}
}
Blittable Structs for GPU/Network
For data that crosses GPU or network boundaries, use blittable structs:
[StructLayout(LayoutKind.Sequential)]
public struct AnimationBlendState
{
public int ClipIndex1; // 4 bytes
public float ClipTime1; // 4 bytes
public int ClipIndex2; // 4 bytes
public float ClipTime2; // 4 bytes
public float BlendWeight; // 4 bytes
}
Rules: no reference type fields, no bool (use int), explicit layout. Enables Span<T> access and zero-copy serialization via MemoryMarshal.
Referencing vvvv-Loaded DLLs
When referencing DLLs already loaded by vvvv (e.g., VL.Fuse), use <Private>false</Private> to prevent copying:
<Reference Include="Fuse">
<HintPath>..\..\path\to\Fuse.dll</HintPath>
<Private>false</Private>
</Reference>
Build Commands
Build a vvvv plugin project:
dotnet build src/MyPlugin.csproj -c Release
Build an entire solution:
dotnet build src/MyPlugin.sln -c Release
C++/CLI Interop
For wrapping native C/C++ libraries:
msbuild MyCLIWrapper/MyCLIWrapper.vcxproj /p:Configuration=Release /p:Platform=x64
C++/CLI projects require Visual Studio (not dotnet CLI) for building.
Common Package Version Ranges
When referencing vvvv packages, use wildcard versions to stay compatible:
<PackageReference Include="VL.Core" Version="2025.7.*" />
This ensures your plugin works with any patch release of the target vvvv version.
Directory.Build.props
For multi-project solutions, centralize settings:
<Project>
<PropertyGroup>
<TargetFramework>net8.0</TargetFramework>
<ManagePackageVersionsCentrally>true</ManagePackageVersionsCentrally>
</PropertyGroup>
</Project>
COM Interop Pitfalls (DX11/DX12)
When working with COM objects (Direct3D, DXGI):
ComPtr<T>is a struct with no finalizer — if it goes out of scope withoutDispose(), the COM ref leaks- Always return ComPtrs to pools or explicitly Dispose them
IDXGISwapChain::ResizeBuffersfails if any command list on the queue is in recording state
For forwarding .NET libraries into VL (wrapping without new types, pin modifications, event wrapping), see forwarding.md.
Threading Considerations
Update()is always called on the VL main thread- Use
SynchronizationContextto post back to the VL thread from background tasks:
private SynchronizationContext _vlSyncContext;
public MyNode()
{
_vlSyncContext = SynchronizationContext.Current!;
}
// From background thread:
_vlSyncContext.Post(_ => { /* runs on VL thread */ }, null);
More from tebjan/vvvv-skills
vvvv-spreads
Helps write code using vvvv gamma's Spread<T> immutable collection type and SpreadBuilder<T>. Use when working with Spreads, SpreadBuilder, collections, arrays, iteration, mapping, filtering, zipping, accumulating, or converting between Span and Spread. Trigger whenever the user writes collection-processing C# code in vvvv — even if they say 'list', 'array', or 'IEnumerable' instead of Spread, this skill likely applies.
47vvvv-fundamentals
Explains vvvv gamma core concepts — data types, frame-based execution model, pins, pads, links, node browser, live compilation (source project vs binary reference workflows), .vl document structure, file types (.vl/.sdsl/.cs/.csproj), ecosystem overview, and AppHost runtime detection. Use when the user asks about vvvv basics, how vvvv works, the live reload model, when to patch vs code, or needs an overview of the visual programming environment.
47vvvv-channels
Helps work with vvvv gamma's Channel system from C# — IChannelHub, public channels, [CanBePublished] attributes, hierarchical data propagation, channel subscriptions, bang channels, and spread sub-channels. Use when reading or writing public channels from C# nodes, publishing .NET types as channels, working with IChannelHub, subscribing to channel changes, managing hierarchical channel state, or implementing reactive/observable data flow. Trigger for any mention of IChannel, IChannelHub, reactive binding, observable state, two-way data binding, or TryGetChannel in a vvvv context.
46vvvv-node-libraries
Helps set up C# library projects that provide nodes to vvvv gamma — project directory structure, Initialization.cs with AssemblyInitializer, service registration via RegisterService, IResourceProvider factories, ImportAsIs / ImportNamespace / ImportType selection, category organization, .csproj setup, and dynamic node factories via RegisterNodeFactory. Use when creating a new vvvv library, VL package, NuGet package for vvvv, deciding which import attribute to use, organizing categories, controlling which public types become nodes, registering services or node factories, or setting up the project structure. Trigger when the user says 'create a package', 'make a library', 'distribute nodes', 'organize categories', 'hide internal helpers from the node browser', or 'publish a VL package'.
46vvvv-shaders
Helps write SDSL shaders for Stride and vvvv gamma — TextureFX, shader mixins, compute shaders, and ShaderFX composition. SDSL is a superset of HLSL, so use this skill when writing or debugging .sdsl shader files, GPU shaders, visual effects, HLSL code for vvvv, working with the Stride rendering pipeline, composing shader mixins, or any GPU/compute work. Trigger even if the user says 'HLSL', 'shader', 'GPU effect', 'render pass', or 'compute' in a vvvv context.
45vvvv-patching
Explains vvvv gamma visual programming patterns — dataflow, node connections, regions (ForEach/If/Switch/Repeat/Accumulator), channels for reactive data flow, event handling (Bang/Toggle/FrameDelay/Changed), patch organization, and common anti-patterns (circular dependencies, polling vs reacting, ignoring Nil). Use when the user asks about patching best practices, dataflow patterns, event handling, or how to structure visual programs.
45