Description
runComputeOnCpu is a function that simulates a GPU-like compute environment on the CPU. It organizes work into workgroups and invocations, similar to how compute shaders operate on GPUs.
Warning
Using barrier() within conditional branches leads to undefined behavior. The emulator is modeled using a single barrier that must be accessible from all threads within a workgroup.
Parameters
- numWorkGroups: UVec3 The number of workgroups in each dimension (x, y, z).
- workGroupSize: UVec3 The size of each workgroup in each dimension (x, y, z).
- compute: ThreadGenerator[A, B, C] The compute shader procedure to execute.
- ssbo: A Storage buffer object(s) containing the data to process.
- smem: B Shared memory for each workgroup.
- args: C Additional arguments passed to the compute shader.
Compute Function Signature
The compute shader procedure should have the following signature:
proc computeFunction[A, B, C]( buffers: A, # Storage buffer (typically ptr T or Locker[T]) shared: ptr B, # Shared memory args: C # Additional arguments ) {.nimcall.}
Example
type Buffers = object input, output: seq[float32] Shared = seq[float32] Args = object factor: int32 proc myComputeShader( buffers: ptr Buffers, shared: ptr Shared, args: Args) {.computeShader.} = # Computation logic here let numWorkGroups = uvec3(4, 1, 1) let workGroupSize = uvec3(256, 1, 1) var buffers: Buffers let coarseFactor = 4'i32 runComputeOnCpu( numWorkGroups, workGroupSize, myComputeShader, addr buffers, newSeq[float32](workGroupSize.x), Args(factor: coarseFactor) )
CUDA to GLSL Translation Table
| CUDA Concept | GLSL Equivalent | Description |
|---|---|---|
| blockDim | gl_WorkGroupSize | The size of a thread block (CUDA) or work group (GLSL) |
| gridDim | gl_NumWorkGroups | The size of the grid (CUDA) or the number of work groups (GLSL) |
| blockIdx | gl_WorkGroupID | The index of the current block (CUDA) or work group (GLSL) |
| threadIdx | gl_LocalInvocationID | The index of the current thread within its block (CUDA) or work group (GLSL) |
| blockIdx * blockDim + threadIdx | gl_GlobalInvocationID | The global index of the current thread (CUDA) or invocation (GLSL) |
Types
GlEnvironment = object gl_GlobalInvocationID*: UVec3 ## Global ID of the current invocation gl_LocalInvocationID*: UVec3 ## Local ID within the workgroup gl_WorkGroupID*: UVec3 ## ID of the current workgroup gl_WorkGroupSize*: UVec3 ## Size of the workgroup (x, y, z) gl_NumWorkGroups*: UVec3 ## Total number of workgroups (x, y, z) gl_NumSubgroups*: uint32 ## Number of subgroups in the workgroup gl_SubgroupSize*: uint32 ## Size of each subgroup gl_SubgroupID*: uint32 ## ID of the current subgroup [0..gl_NumSubgroups) gl_SubgroupInvocationID*: uint32 ## ID of the invocation within the subgroup [0..gl_SubgroupSize)
- Source Edit
ThreadGenerator[A; B; C] = proc (env: GlEnvironment; buffers: A; shared: ptr B; args: C): ThreadClosure {.nimcall.}
- Source Edit
Procs
proc runComputeOnCpu[A, B, C](numWorkGroups, workGroupSize: UVec3; compute: ThreadGenerator[A, B, C]; ssbo: A; smem: B; args: C)
- Source Edit