# `CauldronGPU.Host`
[🔗](https://github.com/jaman/cauldron/blob/v0.3.3/cauldron_gpu/lib/cauldron_gpu/host.ex#L1)

The renderer in its own OS process (`priv/native/<system architecture>/cauldron_gpu_host`),
so a crash in it leaves the VM running. The functions take the same arguments and
return the same values as `CauldronGPU`'s; a caller switches by module.

    {:ok, gpu} = CauldronGPU.Host.open(window: false, width: 640, height: 360)
    cube = CauldronGPU.Host.mesh(gpu, CauldronGPU.Mesh.cube(1.0))
    CauldronGPU.Host.submit(gpu, [{:instance, 1, %CauldronGPU.Instance{mesh: cube}}])

A server process owns the renderer process and keeps the scene sent to it. When the
renderer process exits, the `:events` process receives
`{:cauldron_gpu, window_id, :renderer_exited}`; `restart/1` starts a new one and sends
it the kept scene (meshes, textures, materials, instances, poses, lights, camera,
environment, effects). Changes submitted while the renderer is down are kept and
answered with `{:error, "renderer exited"}`. `window_id` stays the same across
restarts. Other events are those of `CauldronGPU`.

Handles are not freed by garbage collection. `release/2` releases one; every handle a
process made is released when that process exits. A released object is freed once no
scene entry uses it. The server stops when the process that called `open/1` exits.

Change batches of `:shared_memory_threshold` bytes or more (default 262144) reach the
renderer through a POSIX shared-memory object rather than the pipe.

# `t`

```elixir
@type t() :: %CauldronGPU.Host{
  id: non_neg_integer(),
  info: CauldronGPU.info(),
  server: pid()
}
```

# `backends`

```elixir
@spec backends() :: [:metal | :vulkan]
```

The backends the renderer was built with, preferred first.

# `canvas`

```elixir
@spec canvas(t(), CauldronGPU.Canvas.t()) :: CauldronGPU.Handle.t()
```

Makes a canvas and returns its handle, a texture's.

# `capture`

```elixir
@spec capture(t(), timeout(), keyword()) ::
  {:ok,
   %{width: pos_integer(), height: pos_integer(), shared_memory: String.t()}}
  | {:ok, %{width: pos_integer(), height: pos_integer(), pixels: binary()}}
  | {:error, term()}
```

The next drawn frame; see `CauldronGPU.capture/3`.

# `child_spec`

Returns a specification to start this module under a supervisor.

See `Supervisor`.

# `close`

```elixir
@spec close(t()) :: :ok
```

Closes the window and stops the renderer process and its server.

# `frames`

```elixir
@spec frames(t()) :: non_neg_integer()
```

How many frames the renderer process has drawn since it started.

# `material`

```elixir
@spec material(t(), CauldronGPU.Material.t()) :: CauldronGPU.Handle.t()
```

Defines a material and returns its handle.

# `mesh`

```elixir
@spec mesh(t(), CauldronGPU.Mesh.t()) :: CauldronGPU.Handle.t()
```

Uploads a mesh and returns its handle.

# `open`

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

Starts a renderer process and opens a window or offscreen device in it. Options are
those of `CauldronGPU.open/1`, plus `:shared_memory_threshold`.

# `os_pid`

```elixir
@spec os_pid(t()) :: non_neg_integer() | nil
```

The renderer's OS process id, or `nil` while it is down.

# `relative_mouse`

```elixir
@spec relative_mouse(t(), boolean()) :: :ok | {:error, String.t()}
```

Hides the pointer and reports only relative motion while `enabled`.

# `release`

```elixir
@spec release(t(), CauldronGPU.Handle.t()) :: :ok
```

Releases a handle: the renderer frees its object once no scene entry uses it.

# `remove_shared_memory`

```elixir
@spec remove_shared_memory(String.t()) :: :ok
```

Removes the POSIX shared-memory object `name`, if there is one.

# `resize`

```elixir
@spec resize(t(), pos_integer(), pos_integer()) :: :ok | {:error, String.t()}
```

Changes an offscreen device's picture size (`window: false`).

# `restart`

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

Starts a new renderer process after the previous one exited and sends it the kept
scene. `{:error, "running"}` while the renderer is alive.

# `submit`

```elixir
@spec submit(t(), [CauldronGPU.Stream.change()]) :: :ok | {:error, String.t()}
```

Sends one tick of changes (see `CauldronGPU.Stream`); a `:tick` is put before them.

# `terminal_size`

```elixir
@spec terminal_size() :: {:ok, map()} | {:error, String.t()}
```

The size of the terminal the VM runs in; see `CauldronGPU.terminal_size/0`.

# `texture`

```elixir
@spec texture(t(), CauldronGPU.Texture.t()) :: CauldronGPU.Handle.t()
```

Uploads a texture and returns its handle.

---

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