# `ExBurn.CubeclBridge`
[🔗](https://github.com/ohhi-vn/ex_burn/blob/main/lib/ex_burn/cubecl_bridge.ex#L1)

Bridge to ExCubecl for GPU execution via Burn's CubeCL backend.

CubeCL (Compute Unified Backend for Compute Language) is Burn's
GPU compute abstraction layer that supports:

- **CUDA** (NVIDIA GPUs)
- **Metal** (Apple GPUs — iOS, macOS)
- **Vulkan** (Android, Linux, Windows)
- **WebGPU** (Browser-based GPU)
- **ROCm** (AMD GPUs)

This module delegates to the ExCubecl library (v0.4.0) for all GPU
operations. ExCubecl buffers (opaque references) are used for GPU
memory throughout.

## Usage

    # Check if a GPU is available
    if ExBurn.CubeclBridge.available?() do
      # Initialize the GPU context
      {:ok, ctx} = ExBurn.CubeclBridge.init(:metal)

      # Check device capabilities
      caps = ExBurn.CubeclBridge.device_capabilities(ctx)

      # Allocate GPU buffer and run a kernel
      {:ok, buf} = ExBurn.CubeclBridge.allocate_gpu(ctx, [4, 4], :f32)
      {:ok, result} = ExBurn.CubeclBridge.execute(ctx, :add, [buf, buf])

      # Pipeline for multi-kernel execution
      {:ok, pid} = ExBurn.CubeclBridge.pipeline()
      :ok = ExBurn.CubeclBridge.pipeline_add(pid, :add, [buf, buf], buf)
      :ok = ExBurn.CubeclBridge.pipeline_add(pid, :relu, [buf], buf)
      {:ok, commands} = ExBurn.CubeclBridge.pipeline_run(pid)
      :ok = ExBurn.CubeclBridge.pipeline_free(pid)
    end

# `backend`

```elixir
@type backend() :: :cuda | :metal | :vulkan | :wgpu | :rocm
```

# `buffer`

```elixir
@type buffer() :: reference()
```

# `command_id`

```elixir
@type command_id() :: non_neg_integer()
```

# `context`

```elixir
@type context() :: reference()
```

# `kernel`

```elixir
@type kernel() :: atom()
```

# `pipeline_id`

```elixir
@type pipeline_id() :: non_neg_integer()
```

# `allocate_gpu`

```elixir
@spec allocate_gpu(context(), [non_neg_integer()], atom()) ::
  {:ok, buffer()} | {:error, String.t()}
```

Allocates a GPU buffer with the given shape and type.

Returns an ExCubecl buffer reference.

# `async_poll`

```elixir
@spec async_poll(command_id()) ::
  {:ok, :pending | :running | :completed | :failed} | {:error, term()}
```

Polls the status of an asynchronous command.

Returns `:pending`, `:running`, `:completed`, or `:failed`.

# `async_submit`

```elixir
@spec async_submit(ExCubecl.Command.t()) :: {:ok, command_id()} | {:error, term()}
```

Submits a command for asynchronous execution.

Returns a command ID that can be polled or waited on.

# `async_wait`

```elixir
@spec async_wait(command_id()) :: :ok | {:error, term()}
```

Blocks until the given command completes.

# `available?`

```elixir
@spec available?() :: boolean()
```

Checks whether a GPU device is available via ExCubecl.

# `available_backends`

```elixir
@spec available_backends() :: [backend()]
```

Returns a list of available GPU backends on this system.

Delegates to ExCubecl availability checks and platform detection.

# `buffer_dtype`

```elixir
@spec buffer_dtype(buffer()) :: {:ok, String.t()} | {:error, term()}
```

Returns the data type of a GPU buffer.

# `buffer_read`

```elixir
@spec buffer_read(buffer()) :: {:ok, binary()} | {:error, term()}
```

Reads the raw binary data from a GPU buffer.

# `buffer_read!`

```elixir
@spec buffer_read!(buffer()) :: binary()
```

Reads the raw binary data from a GPU buffer, raising on error.

# `buffer_shape`

```elixir
@spec buffer_shape(buffer()) :: {:ok, [non_neg_integer()]} | {:error, term()}
```

Returns the shape of a GPU buffer.

# `buffer_size`

```elixir
@spec buffer_size(buffer()) :: {:ok, non_neg_integer()} | {:error, term()}
```

Returns the size of a GPU buffer in bytes.

# `compile_kernel`

```elixir
@spec compile_kernel(context(), kernel(), keyword()) ::
  {:ok, reference()} | {:error, String.t()}
```

Compiles a compute kernel for the given backend.

Kernels are managed by ExCubecl; this function verifies the kernel
is available and returns a reference.

# `destroy`

```elixir
@spec destroy(context()) :: :ok
```

Destroys the GPU context and frees all associated resources.

# `device_capabilities`

```elixir
@spec device_capabilities(context()) :: map()
```

Returns the capabilities of the GPU device.

# `device_count`

```elixir
@spec device_count() :: {:ok, non_neg_integer()} | {:error, term()}
```

Returns the number of GPU devices available.

# `device_to_host`

```elixir
@spec device_to_host(context(), buffer()) ::
  {:ok, Nx.Tensor.t()} | {:error, String.t()}
```

Copies data from a GPU buffer to host (CPU) as an Nx tensor.

## Parameters

  * `ctx` — The GPU context
  * `buffer` — An ExCubecl buffer reference

## Returns

  `{:ok, Nx.Tensor.t()}` on success, `{:error, reason}` on failure.

# `execute`

```elixir
@spec execute(context(), kernel(), [buffer()], keyword()) ::
  {:ok, buffer()} | {:error, String.t()}
```

Executes a compute kernel on the GPU.

## Parameters

  * `ctx` — The GPU context
  * `kernel` — The kernel to execute (atom)
  * `args` — List of ExCubecl buffer references
  * `opts` — Options (currently unused, reserved for future use)

## Returns

  `{:ok, result_buffer}` on success, `{:error, reason}` on failure.

# `free`

```elixir
@spec free(context(), buffer()) :: :ok
```

Frees a GPU buffer.

Note: ExCubecl buffers are garbage-collected when their reference
goes out of scope. This function is a no-op for API compatibility.

# `host_to_device`

```elixir
@spec host_to_device(context(), Nx.Tensor.t()) ::
  {:ok, buffer()} | {:error, String.t()}
```

Copies data from host (CPU) to a new GPU buffer.

## Parameters

  * `ctx` — The GPU context
  * `tensor` — An Nx tensor to copy to the GPU

## Returns

  `{:ok, buffer}` on success, `{:error, reason}` on failure.

# `init`

```elixir
@spec init(
  backend(),
  keyword()
) :: {:ok, context()} | {:error, String.t()}
```

Initializes a GPU compute context for the given backend.

## Parameters

  * `backend` — The GPU backend to use (`:cuda`, `:metal`, `:vulkan`, `:wgpu`, `:rocm`)
  * `opts` — Options (currently unused, reserved for future use)

## Returns

  `{:ok, context}` on success, `{:error, reason}` on failure.

# `kernels`

```elixir
@spec kernels() :: {:ok, [String.t()]} | {:error, term()}
```

Returns the list of kernel names supported by ExCubecl.

# `memory_total`

```elixir
@spec memory_total(context()) :: non_neg_integer()
```

Returns the total available GPU memory (in bytes).

Note: ExCubecl does not currently expose memory usage statistics.
This always returns 0.

# `memory_used`

```elixir
@spec memory_used(context()) :: non_neg_integer()
```

Returns the amount of GPU memory currently in use (in bytes).

Note: ExCubecl does not currently expose memory usage statistics.
This always returns 0.

# `pipeline`

```elixir
@spec pipeline() :: {:ok, pipeline_id()} | {:error, term()}
```

Creates a new pipeline for multi-kernel execution.

# `pipeline_add`

```elixir
@spec pipeline_add(pipeline_id(), atom(), [buffer()], buffer(), map()) ::
  :ok | {:error, term()}
```

Adds a kernel command to a pipeline.

## Parameters

  * `pipeline_id` — The pipeline to add to
  * `kernel` — Kernel name (atom)
  * `inputs` — List of input buffer references
  * `output` — Output buffer reference
  * `params` — Additional parameters (optional, default: `%{}`)

# `pipeline_add_struct`

```elixir
@spec pipeline_add_struct(pipeline_id(), ExCubecl.Command.t()) ::
  :ok | {:error, term()}
```

Adds a pre-built `%ExCubecl.Command{}` struct to a pipeline.

# `pipeline_free`

```elixir
@spec pipeline_free(pipeline_id()) :: :ok | {:error, term()}
```

Frees a pipeline and its associated resources.

# `pipeline_run`

```elixir
@spec pipeline_run(pipeline_id()) :: {:ok, [command_id()]} | {:error, term()}
```

Executes all commands in the pipeline and returns their command IDs.

# `supported_dtypes`

```elixir
@spec supported_dtypes() :: [atom()]
```

Returns the list of supported data types.

# `synchronize`

```elixir
@spec synchronize(context()) :: :ok
```

Synchronizes the GPU context, blocking until all queued operations complete.

Note: ExCubecl does not expose a global synchronization primitive.
Use `async_wait/1` on specific command IDs for fine-grained control.

# `version`

```elixir
@spec version() :: String.t()
```

Returns the ExCubecl library version string.

---

*Consult [api-reference.md](api-reference.md) for complete listing*
