Kernel APIs define generated compute shader shapes and shader-only runtime markers such as thread IDs, barriers, shared memory, and atomics.
[Kernel]
[ThreadGroupSize(DefaultThreadGroupSizes.X)]
public readonly partial struct MyKernel(ReadWriteBuffer<float> data) : IKernel1D
{
public void Execute()
{
int i = ThreadIds.X;
data[i] = data[i] + 1.0f;
}
}| Interface | Dispatch size | Thread ID helper |
|---|---|---|
IKernel1D |
int |
ThreadIds.X |
IKernel2D |
int2 |
ThreadIds.XY |
IKernel3D |
int3 |
ThreadIds.XYZ |
| API | Meaning |
|---|---|
ThreadIds.X/Y/Z |
Global invocation components. |
ThreadIds.XY/XYZ |
Global invocation vectors. |
LocalIds.X/Y/Z |
Local workgroup invocation components. |
GroupIds.X/Y/Z |
Workgroup ID components. |
DispatchSize.X/Y/Z |
Logical dispatch size. |
GroupSize.X/Y/Z |
Declared local group size. |
These properties are shader-only markers and throw on the CPU.
GPU.Dispatch(new Kernel1D(...), count);
GPU.Dispatch(new Kernel2D(...), new int2(width, height));
GPU.Dispatch(new Kernel3D(...), new int3(width, height, depth));
DispatchPath path = GPU.DispatchAndGetPath(new Kernel1D(...), count);wait defaults to true. Use DispatchAndGetPath in samples and tests when you need to prove the native route.
Kernel-local helper:
[Callable]
private static float Smooth(float x)
{
return x * x * (3.0f - (2.0f * x));
}Reusable helper library:
[ShaderLibrary]
public static class Brdf
{
[Callable]
public static float3 Diffuse(float3 albedo, float nDotL)
{
return albedo * ShaderMath.Clamp(nDotL, 0.0f, 1.0f);
}
}Callables must use supported shader value types. Overloads bind by generated symbol identity. [ShaderLibrary] callables must be static and source-available to the consuming compilation.
[GpuStruct] instance callables are supported. Feather lowers the receiver as an explicit first parameter. Read-only receiver methods use an in parameter. Methods that assign to this or a nested receiver field use an inout receiver, so calls on locals and ReadWriteBuffer<T> elements can write back through the original l-value.
[GpuStruct]
public partial struct Counter
{
public float Value;
[Callable]
public void Add(float amount)
{
Value += amount;
}
}Mutating receiver calls require an addressable receiver. A call on a temporary value, or on an element from a read-only resource, is rejected by the generator.
Shader callables may use generic type parameters when every use can be monomorphized from concrete GPU value types. The supported object-style pattern is an interface constraint implemented by [GpuStruct] types:
public interface IShape
{
float Sdf(float3 p);
}
[GpuStruct]
public readonly partial record struct Sphere(float Radius) : IShape
{
[Callable]
public float Sdf(float3 p) => ShaderMath.Length(p) - Radius;
}
[ShaderLibrary]
public static class ShapeOps
{
[Callable]
public static float Eval<TShape>(TShape shape, float3 p)
where TShape : IShape
{
return shape.Sdf(p);
}
}Each concrete call, such as Eval<Sphere>, emits a separate callable and directly calls Sphere.Sdf. Feather does not lower interface-typed locals, virtual dispatch, reference identity, vtables, or class inheritance into GPU code.
var shared = new SharedMemory<float>(256);
shared[LocalIds.X] = input[ThreadIds.X];
GpuBarrier.Workgroup();
output[ThreadIds.X] = shared[LocalIds.X];SharedMemory<T> is shader-only and intended for workgroup-local scratch storage.
| API | Purpose |
|---|---|
GpuBarrier.Workgroup() |
Workgroup execution/memory barrier. |
GpuBarrier.Memory() |
Memory barrier. |
GpuBarrier.Full() |
Combined barrier. |
Barriers are shader markers and throw if called on the CPU.
Integer atomics operate on supported l-values:
GpuAtomic.Add(ref counters[0], 1);
GpuAtomic.CompareExchange(ref values[i], expected, replacement);| API | Operation |
|---|---|
Add |
Atomic add. |
Sub |
Atomic subtract. |
Min / Max |
Atomic min/max. |
And / Or / Xor |
Atomic bitwise operations. |
Exchange |
Atomic exchange. |
CompareExchange |
Atomic compare-exchange. |
Most code uses GPU.Dispatch. GpuKernel is available for lower-level inspection and dispatch:
| API | Purpose |
|---|---|
GpuKernel.Create<TKernel>(context) |
Creates a native kernel object. |
GpuKernel.Dispatch(...) |
Dispatches with an explicit context/kernel object. |
GetGLSL() |
Returns unoptimized GLSL. |
GetOptimizedGLSL() |
Returns backend-optimized GLSL inspection text. |
LastDispatchPath |
Last native route. |
GPU.DispatchandGpuKernelare host APIs.ThreadIds,LocalIds,GroupIds,DispatchSize,GroupSize,GpuBarrier,GpuAtomic, andSharedMemory<T>are shader-only markers.[Callable]methods are ordinary C# declarations at compile time, but their bodies must fit the shader subset.[ShaderLibrary]is a compile-time import marker; it does not register runtime functions.- Generic interface callables are compile-time monomorphization only; runtime interface dispatch remains unsupported.
GpuKernelis disposable when you create one explicitly.- Most applications use
GPU.Dispatch, which creates and releases native kernel state for that dispatch. - Shader-only marker APIs throw when called on the CPU.
- Unsupported statements/calls produce generator diagnostics before dispatch.
samples/HelloBuffersamples/GpuStructInterfacessamples/ParallelReductionsamples/Histogramtests/Feather.Integration.Tests/GeneratedComputeDispatchTests.cstests/Feather.Integration.Tests/ShaderDslCoverageTests.cs