v0.5.0

Creates and manages SDL3/Vulkan windows. Most games open a single window at bootstrap time.

A window is only a presentation target. It does not automatically display the current board. Attach a board with Syncromesh/Board.attach(boardId, windowId) or attachOffset(...) before expecting entity renderables to appear.

Import #

import * as Window from 'Syncromesh/Window';

Functions #

window
Creates a new window and returns its ID.
  • The returned ID is used by Helix/Event and Helix/UserInterface for window-scoped operations.
  • Entity renderables are drawn from attached boards. Use Board.attach(Board.current(), windowId) for the current board, or attach a separately created board.
  • Pass postFx to configure the initial post-processing chain.
window(options: WindowOptions): Promise<number>
setPostFx
Replaces the window's post-processing configuration.
setPostFx(windowId: number, config: PostFxConfig): Promise<boolean>
setSceneBackground
Draws one native fullscreen background before all board render buffers.
  • The shader receives the window camera position and frame, viewport size, renderer time, and the supplied seed through the standard push constants.
  • An optional texture is bound as the shader's primary sampler and loaded once when the background is installed.
  • Use this for scene backgrounds that must remain independent of board lifecycle and composition.
setSceneBackground(windowId: number, config: SceneBackgroundConfig): Promise<boolean>
clearSceneBackground
Removes the window's scene background.
clearSceneBackground(windowId: number): Promise<boolean>
setPostFxEnabled
Enables or disables the whole post-processing chain.
setPostFxEnabled(windowId: number, enabled: boolean): Promise<boolean>
setPostFxPassEnabled
Enables or disables one post-processing pass by ID.
setPostFxPassEnabled(windowId: number, passId: string, enabled: boolean): Promise<boolean>
setPostFxParam
Updates one parameter on a post-processing pass.
setPostFxParam(windowId: number, passId: string, paramName: string, value: PostFxParam): Promise<boolean>
patchPostFxParams
Updates multiple parameters on a post-processing pass.
patchPostFxParams(windowId: number, passId: string, params: Record<string, PostFxParam>): Promise<boolean>
close
Closes all open windows.
close(): Promise<void>

WindowOptions #

WindowOptions
Configuration for creating a window.
  • width number — Window width in pixels.
  • height number — Window height in pixels.
  • title string — Window title.
  • state string optional — Set to "fullscreen" for a fullscreen window. Omit for windowed mode.
  • postFx PostFxConfig optional — Initial post-processing configuration for this window.
  • deviceSelector (request: VulkanDeviceSelectionRequest) => string | PromiseLike<string> optional — Selects a suitable GPU for this window; the callback has a five-second deadline.
VulkanDeviceSelectionRequest
Surface-specific candidates. Candidate IDs are opaque and valid only for this request.
  • window { runtime, title, role, logicalWidth, logicalHeight, fullscreen, transparent, display }
  • preferredDeviceId string — Discrete-first native recommendation.
  • devices VulkanDeviceCandidate[]
VulkanDeviceCandidate
Device properties, driver metadata, UUIDs, advertised extensions, core/versioned features, raw limits, memory, queues, suitability, and structured rejection reasons. 64-bit values are bigint.
  • id, index, name, type, vendorId, deviceId string | number
  • suitable boolean
  • rejections { code: string, message: string }[]
  • extensions, features, limits, memory, queueFamilies object
PostFxConfig
Fullscreen post-processing chain configuration.
  • enabled boolean optional — Defaults to true when postFx is supplied.
  • passes PostFxPass[] — Ordered fullscreen shader passes. The output of each pass feeds the next pass.
SceneBackgroundConfig
Configuration for the native scene background draw.
  • vert string — SPIR-V fullscreen vertex shader path.
  • frag string — SPIR-V fullscreen fragment shader path.
  • seed number — Unsigned 32-bit seed supplied to the shader.
  • texture string optional — Texture bound to the shader's primary sampler.
  • textureSemantic `'colour' | 'color' | 'data'` optional — Texture colour-space handling. Defaults to colour; use data for packed linear shader data.
PostFxPass
One fullscreen shader pass.
  • id string — Stable ID used by runtime update functions.
  • vert string — SPIR-V fullscreen vertex shader path.
  • frag string — SPIR-V fullscreen fragment shader path.
  • enabled boolean optional — Defaults to true.
  • uiMode `'scene_only' | 'scene_and_ui'` optional 'scene_only' applies before the UI overlay when the renderer can split scene/UI draws. Omit or use 'scene_and_ui' to process the composed frame.
  • params Record<string, PostFxParam> optional — Named shader parameters packed into post-FX uniform slots.
PostFxParam
Typed post-FX shader parameter.
  • type `'float' | 'int' | 'bool' | 'vec2' | 'vec3' | 'vec4'` — Parameter type.
  • value number | boolean | number[] — Scalar value or vector components.

Examples #

import * as Board from 'Syncromesh/Board';
import * as Camera from 'Syncromesh/Camera';
import * as Window from 'Syncromesh/Window';

const windowId = await Window.window({
    width: 1280,
    height: 720,
    title: 'My Game',
    deviceSelector: async ({ devices, preferredDeviceId }) =>
        devices.find(device => device.type === 'discrete' && device.suitable)?.id ?? preferredDeviceId
});

await Board.attach(Board.current(), windowId);
await Camera.setWindow(windowId);

// Fullscreen
const fsId = await Window.window({
    width: 1920,
    height: 1080,
    title: 'My Game',
    state: 'fullscreen'
});

Bloom and Tonemapping #

Post-FX render targets use an HDR float format when supported, then the final pass should tonemap back to the window output. The bundled ACES tonemap shader is postfx_tonemap_aces.frag.spv; custom tonemapping is supported by replacing that fragment shader with your own fullscreen shader.

uiMode: 'scene_only' is intended for effects such as world bloom that should not process the UI. The current renderer split requires single-sample rendering; with MSAA active, scene-only effects may include UI.

import * as Window from 'Syncromesh/Window';

const VERT = '/rom/shaders/postfx/postfx_fullscreen.vert.spv';

const windowId = await Window.window({
    width: 1280,
    height: 720,
    title: 'Space RTS',
    postFx: {
        enabled: true,
        passes: [
            {
                id: 'engine-bloom',
                vert: VERT,
                frag: '/rom/shaders/postfx/postfx_bloom.frag.spv',
                uiMode: 'scene_only',
                params: {
                    threshold: { type: 'float', value: 1.0 },
                    intensity: { type: 'float', value: 0.6 },
                    radius: { type: 'float', value: 4.0 }
                }
            },
            {
                id: 'tonemap',
                vert: VERT,
                frag: '/rom/shaders/postfx/postfx_tonemap_aces.frag.spv',
                uiMode: 'scene_and_ui',
                params: {
                    exposure: { type: 'float', value: 1.0 }
                }
            }
        ]
    }
});

await Window.setPostFxParam(windowId, 'tonemap', 'exposure', { type: 'float', value: 1.15 });