Dynamic DX11 Buffers in VL

January 31, 2018 posted by: tonfilm

Dynamic Buffers

Current vvvv alpha and upcoming vvvv beta36 has a new set of nodes that allows you to quickly upload data from VL to the graphics card. We had a WIP forum discussion about it here: VL - Custom Dynamic Buffer

On the VL side the nodes are called ToBufferDescription and we have them for the basic data types that usually hold big chunks of data: Spread, Array, IntPtr and Stream. The vvvv side is rather easy and only has one node called UploadBuffer (DX11.Buffer)node.

Primitive Data Types

Primitive types work out of the box and don’t need any special treatment. Just make sure you define the correct Buffer type in the shader. This works for Integers, Floats, Vectors and so on, everything that is available in the shader as primitive type. Here is an example for Float32:

The only exception is Matrix it needs to be transposed in order to work like a normal transformation input. If you send a large amount of individual matrices to the shader the most efficient way is to do the transpose in the shader directly:

If the same matrix is re-used very often or you don’t have access to the shader code simply transpose in VL:

Custom Data Types

If you want to define your own data types like light information or a custom vertex type in the shader then you need to pack the data accordingly in the buffer description. For this task the ToBufferDescription (Stride) nodes are used. They allow you to make a buffer description out of primitive types like float or even byte and set the stride size of your custom type in bytes so that the shader can read the custom type directly out of the buffer.

Matrix hint: If you define a matrix in a custom type in the shader you can use the row_major modifier to automate the transpose operation.

struct MyLightType
{
	float3 Direction;
	float Brightness; 
	row_major float4x4 Transformation; //set matrix type
}; 

Performance hint: If you can, design your custom types in a way that the byte count is a multiple of 16, sometimes it makes sense to insert unused floats as padding:

//would have 20 bytes, but blown up to 32 bytes (2 x 16) for faster read performance
struct Circle
{
    float4 Position;
    float  Radius;
    float pad0;
    float pad1;
    float pad2;
};

More info: https://developer.nvidia.com/content/understanding-structured-buffer-performance

Custom types in C#

If you are a C# coder you can also define a struct in C# with attribute StructLayout(LayoutKind.Sequential) and the same byte layout, import it in VL and pass that directly into the buffer. Then you don’t need the node with version StrideSize because the data type size already matches.

[](StructLayout(LayoutKind.Sequential))
public struct Circle
{
    public Vector4 Position;
    public float Radius;
    float pad0;
    float pad1;
    float pad2;
public Circle(Vector4 position, float radius)
{
    Position = position;
    Radius = radius;
}

}

Dynamic Raw Buffers

While in the process of doing the dynamic buffer nodes it was easy to add raw buffers. These buffers are from older shader models and can only be filled with bytes. On the shader side however you can also define Custom types. Only difference in HLSL is that you write Buffer instead of StructuredBuffer.

The node set is basically the same except that the VL part is not generic and only accepts bytes as input. The node names are ToRawBufferDescription in VL and UploadBuffer (DX11.Buffer Raw)node in vvvv.

Raw buffers have no advantage except when you have to deal with an older graphics card, driver or shader code.

Examples

A VL patch with shader code can be found in latest alphas girlpower\VL\DX\DynamicBuffersAndTextures.v4p. And it is also used by @mburk for material management in his latest superphysical packbeta-contribution.

So now you can start sending your data up to the card and enjoy the speed. As always, if any questions arise hit us up in the forums.

yours, devvvvs


Comments:

Comments are no longer accepted for this post.

velcrome
17.05.2018 - 21:50

This is really cool and I think I will try to use it in our current project.

Found a really cool Game of Life easteregg inside, much much appreciated.

Was there a reason why you could not implement UploadBuffer (DX11.Buffer)node in vl too? I ask because I am interested in the nitty-gritty technical details, why the actual gpu upload was eventually moved out of vl to this (proprietary) vvvv plugin.

Game of Life looks great in VL after all, including easy array swapping. Much recommended reading material I’d say.

could not resist:

PatchSnippet

Elias
18.05.2018 - 13:53
I think the reason was that one needs to implement the IDX11ResourceHost interface for it to work. This interface would need to be implemented by the VL hosting layer and forwarded to the VL node itself.
tonfilm
18.05.2018 - 13:56
Yes that is right, it would be rather complicated to implement the interfaces, also we wanted to avoid the dependency to vvvv and DirectX in VL.
polyrhythm
28.02.2019 - 08:45
For custom types in C#, this page says that after importing the type, to “simply pass it directly to the buffer.” Which version of the buffer? Spread? I have my types imported into VL but don’t see a way to actually pass it into the buffer or turn my type into a spread (and wouldn’t doing that force me to set the stride anyway?).
tonfilm
28.02.2019 - 14:49
@polyrhythm it means as an Array or Spread. note that YourType needs to be a struct. if you only have one single element you still have to create a Spread or Array, e.g. with the FromValue node.

Contact


Imprint

vvvv - Dießl & Gregor GbR
Oranienstrasse 10
10997 Berlin/Germany
VAT: DE275566955

groupӘvvvv.org

Follow us

Mastodon.social
Pixelfed.social
Github
Vimeo
Youtube

Sign up for our Newsletter

Your subscription could not be saved. Please try again.
Your subscription has been successful.