The cuda Lua Table#
Every function and constant a .cu.lua launch script can use. For what a launch script is
and when it runs, refer to The Lua Launch Script.
Accepted source assets: .cu, compiled with NVRTC on load, and the pre-compiled .ptx,
.cubin and .fatbin. Extensions are matched case-insensitively.
The CUDA headers are reachable from a .cu source through #include, for example
#include <cuda_fp16.h>. They come from one directory, the CUDA installation SPG finds:
CUDA_PATH or CUDA_HOME if either is set in the environment, otherwise the headers bundled
with the renderer. It is the only include directory the compile is given, so a header sitting
beside the .cu does not resolve. Refer to Compile It Yourself.
Describing Outputs#
Output descriptors state what an output has to be; SPG owns the memory.
Function |
Description |
|---|---|
|
A texture-backed output. Preferred for image data. Note the argument order against height-first shapes. |
|
A buffer-backed output of arbitrary shape, up to 8 dimensions. Use for non-image data. |
The same functions describe the node’s memory: storage only the node reads and writes,
kept across frames for as long as the node lives. A memory is stated on self.memory under
its name instead of on outputs, and passed to the kernel with the same wrappers as an
output, as in the snippet below. Refer to
Keep State Across Frames.
cuda.image and cuda.empty also take an optional trailing cuda.stateful, which marks
an output persistent so SPG hands the same resource back next frame instead of a fresh one:
state the scene reads as well.
TrailKernel.cu.lua, from the runnable stateful node example#function trail(inputs, outputs)
local image = inputs["Image"]
-- The input is HdrColor, linear radiance, so no exact dtype is pinned here.
-- shape is 1-indexed: [1] = height (rows), [2] = width (columns).
local height = image.shape[1]
local width = image.shape[2]
-- The feedback framebuffer, kept between executions.
self.memory["History"] = cuda.image(width, height, cuda.float4)
-- Ordinary outputs: published as AOVs and handed out fresh each frame.
outputs["Live"] = cuda.image(width, height, cuda.uchar4)
outputs["Trail"] = cuda.image(width, height, cuda.uchar4)
return cuda.kernel({
args = {
cuda.int(width), -- -> int width
cuda.int(height), -- -> int height
cuda.float(inputs["decay"]), -- -> float decay
cuda.TextureObject(image), -- -> cudaTextureObject_t inputImage
cuda.SurfaceObject(self.memory["History"]), -- -> cudaSurfaceObject_t history
cuda.SurfaceObject(outputs["Live"]), -- -> cudaSurfaceObject_t liveImage
cuda.SurfaceObject(outputs["Trail"]), -- -> cudaSurfaceObject_t trailImage
},
block = { 32, 32 },
grid = { math.ceil(width / 32), math.ceil(height / 32) },
})
end
The Wrappers#
Each wrapper turns a descriptor or a value into the CUDA type the kernel parameter expects.
Function |
Wraps to |
Description |
|---|---|---|
|
|
Read-only, hardware-cached texture access to an input or output resource. |
|
|
Read-write surface access to an output resource. |
|
|
Raw device pointer to an input or output resource. |
|
|
Upload a Lua table of numbers to a GPU device array. An empty table gives the kernel a null pointer. |
|
|
A GPU device array of that shape filled with zeros, ones, or a stated value, passed to the kernel as an uploaded Lua table is. |
|
|
Upload a |
|
the matching C scalar |
Scalar kernel argument. |
Every dtype constant can be called as a scalar constructor, for example cuda.half(1.0).
Vector types accept multiple scalar arguments or a single value-input entry, for example
cuda.float3(x, y, z) or cuda.int2(inputs["size"]).
Kernel Launch#
return cuda.kernel({
args = { --[[ ordered kernel arguments ]] },
block = { bx, by },
grid = { gx, gy },
sharedMemSize = 0,
})
Field |
Description |
|---|---|
|
Ordered kernel arguments, matched against the C signature by position. Required. |
|
Threads per block, as |
|
Blocks per launch, in the same form. Optional. |
|
Dynamic shared memory in bytes, the third argument of |
block and grid map directly to the CUDA launch configuration (<<<grid, block>>>).
Left out, they are derived from the first output’s shape: a block of 16 x 16 x 1, or 256 x 1 x 1
for a rank-1 or rank-0 resource, and a grid covering that shape. Value-inputs blockDimX,
blockDimY and blockDimZ supply the block when the script states no block.
Set block and grid explicitly whenever the iteration domain is not the output image, such as
a kernel whose threads walk a buffer. Refer to Control the Launch Geometry.
dtype Constants#
A numeric vector constructor passes all components as one by-value kernel argument, with
the element type and component count the dtype names. The kernel parameter must match:
cuda.float4 takes a float4 parameter, cuda.double3 a double3, and
cuda.double4 a double4. Use cuda.array for a pointer to the components instead.
Constant |
C Type |
Size |
|---|---|---|
|
bool |
1 byte |
|
unsigned char |
1 byte |
|
uchar4 |
4 bytes |
|
__half, half2, half3, half4 |
2 to 8 bytes |
|
float, float2, float3, float4 |
4 to 16 bytes |
|
int32_t, int2, int3, int4 |
4 to 16 bytes |
|
uint32_t, uint2, uint3, uint4 |
4 to 16 bytes |
|
double, double2, double3, double4 |
8 to 32 bytes |
|
int64_t, uint64_t |
8 bytes |
Cached Computation#
Function |
Description |
|---|---|
|
Call |