9
$\begingroup$

I'm exploring isosurface algorithms on GPU for a bachelor's project (specifically concentrating on just binary in/out voxel data rather than real-valued fields). So I have a CPU implementation of good old marching cubes up and running in OpenFrameworks, and now at the stage of trying to port it to GLSL compute shaders, and considering the pitfalls before I dive in. I've only written vert and frag shaders before so it's all new to me.

My first issue is how to efficiently use a lookup table across dozens or hundreds of threads in a workgroup? I understand a GPU has different kinds of memory for different tasks but not fully sure on how each operates or which type to use.

Paul Bourke's classic copypasta table is a 256*16 array so if using a scalar byte type this can presumably be packed into a 4kb texture or SSBO.

The question is, how to stop the different threads from tripping each other up? Many cubes in each work group can potentially have the same configuration therefore trying to access the same location in the buffer at the same time. Is there a workaround or optimization to deal with this?

$\endgroup$
  • $\begingroup$ If it's a read-only lookup table, you can just use a buffer/texture. You could either pack it into one of the normal texture formats, or you can use some of the newer features of DX11 / OpenGL to have a custom format. UAV in DX11 land, or a texture / shader_image_load_store in OpenGL land. $\endgroup$ – RichieSams Oct 27 '15 at 17:33
  • $\begingroup$ In addition, give this presentation a look: cvg.ethz.ch/teaching/2011spring/gpgpu/cuda_memory.pdf It's for CUDA, but it should give you a better idea of what is happening on the underlying hardware $\endgroup$ – RichieSams Oct 27 '15 at 17:41
  • $\begingroup$ Not a full answer but the smaller amount of memory you use the better, as it will be more likely to fit in caches and have fewer cache misses. If you have interpolatable values, like you are baking out points on a curve into textures, you might check this out as a way to get higher quality curve lookup tables with less memory: blog.demofox.org/2016/02/22/… $\endgroup$ – Alan Wolfe Feb 28 '16 at 4:51
7
$\begingroup$

The best place to put a look up table for a GPU compute shader depends on the size of the lookup table, and the frequency/coherency of access. In your case (you mentioned 4kb), shared local memory would likely be best (assuming you do not need this memory for other purposes in the same kernel). This memory has different names in different APIs, but is the same architectural thing and follows the same performance guidelines:

  • CUDA: threadgroup shared memory
  • DirectCompute: groupshared memory
  • OpenCL: local memory
  • Metal: threadgroup memory
  • OpenGL: shared memory

Storing the lookup table in global memory as a read-only buffer may perform just as well, depending on the cache size(s) of the particular GPU you're running on.

Note that I'm presuming this is a read-only lookup table. A read-write lookup table is a completely different beast, and you don't have any good options there.

$\endgroup$
  • $\begingroup$ There are also cases where a read-only buffer will do better than storing 4kb of read-only data in shared local memory. For example, storing it in local memory may mean that there is a unique copy of your data for every thread group. If the buffer fits in cache, it's quite possible that the cache performs better than local memory for read-only access patterns. $\endgroup$ – John Calsbeek May 20 '16 at 6:17
  • $\begingroup$ Thanks for the feedback guys. I've finished the project I was using this for now, and wound up just using a r8ui readonly buffer texture, which worked pretty nicely :) $\endgroup$ – russ May 30 '16 at 8:01

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.