How to utilize read/write functionality in compute shaders?

Hi there,

I learned today that Vulkan was coming to TouchDesigner and is already implemented in the experimental builds, and I jumped for joy because I can finally use compute shaders on my M1 Max! I have experience with HLSL compute shaders so I understand the basics, but I had a question: how do we actually access the data in the output buffers if we have our GLSL TOP set to Read-Write? I’ve tried the following:

texelFetch(sTD2DInputs[0], ivec2(gl_GlobalInvocationID.xy), 0);
texelFetch(mTDComputeOutputs[0], ivec2(gl_GlobalInvocationID.xy), 0);
imageLoad(sTD2DInputs[0], ivec2(gl_GlobalInvocationID.xy), 0);
imageLoad(mTDComputeOutputs[0], ivec2(gl_GlobalInvocationID.xy), 0);

I’m brand-new to the GLSL compute API, so forgive me if I’m missing something totally obvious. I looked for some kind of “mTDComputeInputs” structure in the docs but couldn’t find anything.

Thank you!

EDIT: I should also mention that texelFetch works normally for me when I route a TOP to the GLSL TOP’s input.

Just an update: tried to accomplish this using a feedback TOP, and as I expected there seems to be some race conditions corrupting the data. Would it instead make sense to just use two GLSL tops in sequence? I’m not 100% familiar with the underlying control flow of TD, but I assume that TOPS execute sequentially and hopefully wait for their ancestor TOP to finish before beginning their own processing.

In case it helps, I’m asking because I’m trying to instantiate some physically-modelled particles and store their data (position, velocity, etc.) in a separate buffer that I would read/write to each frame. I’m open to any suggestion on how to best accomplish this.

For inputs you just use texelFetch and texture(), the inputs are always setup as a sampler* since you can’t change your inputs. For the outputs, they will be setup as an image* which allows you to use imageLoad/imageStore.

Yes, TOPs run in sequence, so the first TOP will complete before the next one starts

1 Like

You can see the order of execution in the Performance Monitor.

1 Like

Hey, if you intend to perform read/write operations to the output buffer you should read this forum thread as you might run into some concurrency issues just like I did : Compute shaders and memory synchronization :smile:

1 Like

Thank you! This encouraged me to recheck my variables—I was forgetting to cast gl_GlobalInvocationID to an ivec2 from a uvec2. Duh. Thank you so much!

Thank you! This will be super useful : )

For anybody still getting an error with this:
imageLoad(mTDComputeOutputs[0], ivec2(gl_GlobalInvocationID.xy), 0);

I changed it to this and it worked:
imageLoad(mTDComputeOutputs[0], ivec2(gl_GlobalInvocationID.xy));