src/computesim

Source   Edit  

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 ConceptGLSL EquivalentDescription
blockDimgl_WorkGroupSizeThe size of a thread block (CUDA) or work group (GLSL)
gridDimgl_NumWorkGroupsThe size of the grid (CUDA) or the number of work groups (GLSL)
blockIdxgl_WorkGroupIDThe index of the current block (CUDA) or work group (GLSL)
threadIdxgl_LocalInvocationIDThe index of the current thread within its block (CUDA) or work group (GLSL)
blockIdx * blockDim + threadIdxgl_GlobalInvocationIDThe global index of the current thread (CUDA) or invocation (GLSL)

Types

GlEnvironment = object
  gl_GlobalInvocationID*: UVec3
  gl_LocalInvocationID*: UVec3
  gl_WorkGroupID*: UVec3
  gl_WorkGroupSize*: UVec3
  gl_NumWorkGroups*: UVec3
  gl_NumSubgroups*: uint32
  gl_SubgroupSize*: uint32
  gl_SubgroupID*: uint32
  gl_SubgroupInvocationID*: uint32
Source   Edit  
ThreadGenerator[A; B; C] = proc (env: GlEnvironment; buffers: A; shared: ptr B;
                                 args: C): ThreadClosure {.nimcall.}
Source   Edit  
ThreadGeneratorNoShared[A; C] = proc (env: GlEnvironment; buffers: A; 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  

Templates

template runComputeOnCpu[A, C](numWorkGroups, workGroupSize: UVec3;
                               compute: ThreadGeneratorNoShared[A, C]; ssbo: A;
                               args: C)
Source   Edit