AsString (EX9.Texture)

Hi Devs!

Hope you’re enjoying this year of dragons.
So I’m (as often) trying to get my data back from the GPU to the CPU.

I’ve recalled that old node AsString (Ex9.Texture)

(noted for this discussion that AsString works with the same mechanism as Writer)

This is a slow node (as is Writer). The critical procedure appears to be the copy from GPU to CPU.

Please check this speed test patch i made.

Some different codecs do take a bit more time than others, but my conclusion is that the variance is too small for the compression step to be the critical factor (apart from png).

GPU to CPU copy

The copy of the image from GPU to CPU seems far too slow. Perhaps also the rendering is being performed in a strange way? (I thought at one point that perhaps it might even be rendering on CPU, but making the geometry exceptionally complex does not slow down the process)

So in quite a pathetic way, I beg, please can this be sped up!
AsVideo is pretty slow also, but works faster and performs the same operation.

Pipet got sped up recently, perhaps this can be related?

Raw output

A really important string format to have would be raw (e.g. L16 would have string length 2 * width * height).

The length of the string (as seen in the speedtest patch) doesn’t have significant effect on the fps, so this shouldn’t be an issue to send through the graph (and of course, should require less processing in total).


I noticed that the speed is not increased by setting the texture format to DXT and using a DDS AsString.

This would be a great feature to have (not as much as raw output!).

Where is it rendered?

Can we have a device selection to chose which GPU renders the data?


If we can get this node working well, then we can get around the need to Texture Input for plugins for a while (especially for copy to CPU operations)

Also for experimental procedures, copying data back to the CPU is really important, and perhaps we’re not very far away from having a few exceptional ways of doing this.

I understand that DirectX 10 and WDDM changes this situation somewhat for the better, but waiting for DX 10, and then an improvement to these nodes subsequently seems like the long way of going about things.

This seems to be what we want:

AsString speedtest.v4p (17.4 kB)

Speedtest patch for Colour Formats attached (using bmp format)

Screenshot at:

note bmp seems to only support RGB8 format (or less) here as all the file sizes are the same. png and some others are different

AsString speedtest (colorformats).v4p (17.5 kB)

also for a fair test, you should pause the rotation of the teapot

hi elliot,

I have only little knowledge of the real internals of this problem, but I got stuck at exactly the same point some time last year, needing to write many frames to disk in an efficient way. I talked to the devs and learned that they use some internal DX9 function for this … I ended up using max msp writing jpegs to disk at an expectable rate of 25-30fps for 1280p material. vvvv does the same at 4-5 frames as you discovered.
I absolutely second the need for a faster rebound of gpu data within v4!

  • eno

From IRC:

[1:33 AM](1:33 AM) this looks super simple:
[1:34 AM](1:34 AM) IDirect3DSurface9::LockRect or
[1:34 AM](1:34 AM) IDirect3DTexture9::LockRect
[1:34 AM](1:34 AM) then you have a D3DLOCKED_RECT
[1:34 AM](1:34 AM) this is defined as:
[1:34 AM](1:34 AM) typedef struct D3DLOCKED_RECT {
[1:34 AM](1:34 AM) INT Pitch;
[1:34 AM](1:34 AM) void *pBits;
[1:35 AM](1:35 AM) Pitch = rows per byte
[1:35 AM](1:35 AM) and supposedly pBits points directly to the data
[1:35 AM](1:35 AM) “Pointer to the locked bits. If a RECT was provided to the LockRect call, pBits will be appropriately offset from the start of the surface.”
[1:37 AM](1:37 AM) ^bytes per row (not rows per byte)

Oi devvvvs!

AsString has another issue, which is it basically uses String type. So each time you use it in a function, it copies the whole data (same when you pass it from pin to pin, hence why the extra slowness). It’s not only passing the memory location.

So using string for any high data volume manipulation is just not a good idea in general.

Also some formats are slower since they not supported natively by bitmap (L16/Floating point), so they prolly need an extra conversion step.

@vux - string is fast enough for a few megs/frame easy though.
at least for some sleazy cpu access to that texture data.

of course it’s a pretty bad idea to use string like this, but there is no better native way to pass around large unformatted data in vvvv. Mentioned byte to azeno, he also says he considered some kind of raw format.

Some raw format would also be a great thing, but since this node exists, it may as well work better.

Do we have to go via a System.Drawing.Bitmap class? It seems we should be able to just lock the bytes and access them directly.

Would love to have any access to this asap. Currently doing silly things like capture card on a 2nd PC, and often switching to oF simply for this feature.

moments later…
just for reference: meanwhile there is a AsRaw (EX9.Texture).