CauldronGPU (CauldronGPU v0.3.3)

Copy Markdown View Source

A window drawn by the graphics card from a scene described in Elixir.

Elixir keeps the world and sends changes; a native render thread draws at the display's rate from its own copy of the scene, interpolating poses between ticks.

{:ok, gpu} = CauldronGPU.open(title: "Demo", width: 1280, height: 720)
cube = CauldronGPU.mesh(gpu, CauldronGPU.Mesh.cube(1.0))
red = CauldronGPU.material(gpu, %CauldronGPU.Material{base_color: {0.8, 0.1, 0.1, 1.0}})

CauldronGPU.submit(gpu, [
  {:instance, 1, %CauldronGPU.Instance{mesh: cube, materials: [red]}},
  {:light, 1, %CauldronGPU.Light{kind: :directional, direction: {-0.4, -1.0, -0.3}, shadows: true}},
  %CauldronGPU.Camera{position: {0.0, 1.0, 4.0}}
])

Window events arrive at the :events process as {:cauldron_gpu, window_id, event}: {:key, :down | :up, key, repeat?} (key an atom such as :w, :space, :left_shift), {:mouse_motion, x, y, dx, dy}, {:mouse_button, :down | :up, button, x, y}, {:mouse_wheel, dx, dy}, {:resized, width, height}, {:focus, boolean}, :close_requested, and {:error, message} when the renderer rejects a change.

On macOS the window runs on the process's main thread, which the first open/1 takes for the rest of the VM's life; wx cannot open windows in the same VM.

Summary

Functions

The backends this build has, preferred first.

Makes a canvas (CauldronGPU.Canvas) and returns its handle, a texture's.

The next drawn frame as {:ok, %{width: w, height: h, pixels: rgba}}: tone-mapped, sRGB-encoded RGBA bytes, rows from the top. Waits up to timeout milliseconds. generated: true returns the next frame made by frame generation instead.

Closes the window. Later calls with gpu return {:error, "closed"}.

How many frames the renderer has drawn into the window.

Defines a material and returns its handle, which keeps its textures' handles.

Uploads a mesh and returns its handle.

Opens a window. Options: :title, :width and :height in points (default 1280×720), :backend (:metal or :vulkan, default the first of backends/0), :events (the pid that receives window events, default the caller), :window (default true).

Hides the pointer and reports only relative motion while enabled.

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

Changes an offscreen device's picture size (window: false). Windows follow their window.

Timing averaged over recent frames: frames drawn, gpu_ms and cpu_ms per frame, the display's refresh_rate (60 when offscreen), and whether frame generation is generating (it runs only when requested and frames take longer than the display's refresh).

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

The size of the terminal the VM runs in: {:ok, %{columns:, rows:, width:, height:}}, cells and pixels (pixels are 0 where the terminal does not report them), or {:error, reason} when there is no terminal.

Uploads a texture and returns its handle.

Types

info()

@type info() :: %{
  backend: :metal | :vulkan,
  device: String.t(),
  ray_tracing: boolean(),
  mesh_shaders: boolean(),
  unified_memory: boolean(),
  upscaling: boolean(),
  frame_generation: boolean()
}

t()

@type t() :: %CauldronGPU{
  id: non_neg_integer(),
  ids: :atomics.atomics_ref(),
  info: info(),
  window: reference()
}

Functions

backends()

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

The backends this build has, preferred first.

canvas(gpu, canvas)

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

Makes a canvas (CauldronGPU.Canvas) and returns its handle, a texture's.

capture(cauldron_gpu, timeout \\ 5000, opts \\ [])

@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 as {:ok, %{width: w, height: h, pixels: rgba}}: tone-mapped, sRGB-encoded RGBA bytes, rows from the top. Waits up to timeout milliseconds. generated: true returns the next frame made by frame generation instead.

shared_memory: name writes the pixels into the POSIX shared-memory object name (at most 31 bytes on macOS, starting with /; an existing object of that name is removed first) instead of returning them, and answers {:ok, %{width: w, height: h, shared_memory: name}}. The reader normally removes it; remove_shared_memory/1 removes one that was never read. Not available on Windows.

close(cauldron_gpu)

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

Closes the window. Later calls with gpu return {:error, "closed"}.

frames(cauldron_gpu)

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

How many frames the renderer has drawn into the window.

material(gpu, material)

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

Defines a material and returns its handle, which keeps its textures' handles.

mesh(gpu, mesh)

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

Uploads a mesh and returns its handle.

open(opts \\ [])

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

Opens a window. Options: :title, :width and :height in points (default 1280×720), :backend (:metal or :vulkan, default the first of backends/0), :events (the pid that receives window events, default the caller), :window (default true).

With window: false nothing appears on screen: width and height are the picture's size in pixels, a frame is drawn for each submit/2 and capture/2, and frames are read with capture/2.

relative_mouse(cauldron_gpu, enabled)

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

Hides the pointer and reports only relative motion while enabled.

remove_shared_memory(name)

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

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

resize(cauldron_gpu, width, height)

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

Changes an offscreen device's picture size (window: false). Windows follow their window.

stats(cauldron_gpu)

@spec stats(t()) :: %{
  frames: non_neg_integer(),
  gpu_ms: float(),
  cpu_ms: float(),
  refresh_rate: float(),
  generating: boolean()
}

Timing averaged over recent frames: frames drawn, gpu_ms and cpu_ms per frame, the display's refresh_rate (60 when offscreen), and whether frame generation is generating (it runs only when requested and frames take longer than the display's refresh).

submit(cauldron_gpu, changes)

@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()

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

The size of the terminal the VM runs in: {:ok, %{columns:, rows:, width:, height:}}, cells and pixels (pixels are 0 where the terminal does not report them), or {:error, reason} when there is no terminal.

texture(gpu, texture)

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

Uploads a texture and returns its handle.