# `tecs.gfx.images` Image identity, residency, and the commands that carry pixels to the backend. A game names an image, hands over its pixels, and receives a small integer that a [`Sprite`](tecs.gfx.Sprite) stores. The backend owns the texture, the view, the sampler, and the bind group; nothing native reaches game code. ```nupp const id = tecs.gfx.images.upload({ name = "tiles/grass", width = 2, height = 2, pixels = grassRgba8, filter = "nearest", }) world:spawn( tecs.ecs.Transform2D(64, 64, 0, 1, 0, 32, 32), tecs.gfx.Tint(1, 1, 1, 1), tecs.gfx.Sprite(id), tecs.gfx.Renderable2D ) ``` An id is permanent and process-wide, in the same way component identity is, so a snapshot stores the name and resolves the id again on load. Uploading a name twice replaces the image behind that same id, and every sprite already pointing at it draws the new pixels on the next frame. Residency is observed rather than waited on. `upload` queues a command and answers immediately with `"pending"`; the host drains the command, reports the outcome, and `stateOf` then answers `"resident"` or `"failed"`. Extraction draws a sprite whose image is not resident against the backend's opaque white fallback, so a missing asset is a visibly untextured quad rather than a dropped entity or a raised error. Pixels are eight-bit RGBA with unassociated alpha, four bytes per texel, in rows running top to bottom. That is the only accepted layout, and the command names it so a later format costs a value rather than a command shape. ## Types ### `Address` _type_ ```nupp type Address = "clamp" | "repeat" | "mirror" ``` Selects what sampling outside the zero-to-one range returns. These identifiers reach configuration a developer writes and are a compatibility surface. ### `Command` _type_ ```nupp type Command = UploadImageCommand | ReleaseImageCommand | MaterialMapsCommand ``` ### `Filter` _type_ ```nupp type Filter = "nearest" | "linear" ``` Selects minification and magnification filtering. These identifiers reach configuration a developer writes and are a compatibility surface. ### `Format` _type_ ```nupp type Format = "rgba8" ``` The pixel layout an upload carries. This value crosses to the backend inside a command and is a compatibility surface. ### `MaterialMaps` _type_ ```nupp type MaterialMaps = { normalMap: integer?, emissionMap: integer?, ormMap: integer? } ``` Optional companion images; omitted channels use neutral material values. ### `MaterialMapsCommand` _record_ ```nupp record MaterialMapsCommand kind: string serial: integer image: integer normalMap: integer emissionMap: integer ormMap: integer end ``` One queued residency request. #### Fields ##### `kind` ```nupp kind: string ``` ##### `serial` ```nupp serial: integer ``` ##### `image` ```nupp image: integer ``` ##### `normalMap` ```nupp normalMap: integer ``` ##### `emissionMap` ```nupp emissionMap: integer ``` ##### `ormMap` ```nupp ormMap: integer ``` ### `ReleaseImageCommand` _record_ ```nupp record ReleaseImageCommand kind: string serial: integer image: integer end ``` Asks the backend to drop one image and everything bound to it. #### Fields ##### `kind` ```nupp kind: string ``` Read-only. Names the command kind, which is a compatibility surface. ##### `serial` ```nupp serial: integer ``` Read-only. Identifies the command for its completion report. ##### `image` ```nupp image: integer ``` Read-only. Selects the process-wide image id to drop. ### `State` _type_ ```nupp type State = "unknown" | "pending" | "resident" | "failed" | "released" ``` Reports where one named image stands with the backend. ### `UploadImageCommand` _record_ ```nupp record UploadImageCommand kind: string serial: integer image: integer width: integer height: integer format: Format sampler: integer pixels: string end ``` Asks the backend to make one image resident under an id. #### Fields ##### `kind` ```nupp kind: string ``` Read-only. Names the command kind, which is a compatibility surface. ##### `serial` ```nupp serial: integer ``` Read-only. Identifies the command for its completion report. ##### `image` ```nupp image: integer ``` Read-only. Selects the process-wide image id the texture lands under. ##### `width` ```nupp width: integer ``` Read-only. Reports the width in texels. ##### `height` ```nupp height: integer ``` Read-only. Reports the height in texels. ##### `format` ```nupp format: Format ``` Read-only. Names the pixel layout. ##### `sampler` ```nupp sampler: integer ``` Read-only. Selects one of the backend's `SAMPLER_COUNT` samplers. ##### `pixels` ```nupp pixels: string ``` Read-only. Carries the texel bytes, which the host copies and forgets. ### `UploadOptions` _type_ ```nupp type UploadOptions = { name: string, width: integer, height: integer, pixels: string, filter: Filter?, address: Address? } ``` The options `upload` accepts. ## Functions ### `complete` _function_ ```nupp function complete(image: integer, serial: integer, ok: boolean, reason: string?): nil ``` Records the backend's outcome for one drained command. A completion that no longer matches the image's newest serial is discarded, so a replacement queued before the previous upload completed keeps its own state. #### Arguments | Name | Type | Description | | --- | --- | --- | | `image` | `integer` | the process-wide image id the command named | | `serial` | `integer` | the command serial the host applied | | `ok` | `boolean` | whether the backend accepted the command | | `reason` | `string?` | the non-empty host failure, required when `ok` is false | #### Returns | Type | Description | | --- | --- | | `nil` | | #### Raises - when a rejection carries no reason ### `drain` _function_ ```nupp function drain(): {Command} ``` Removes the queued residency commands for the host to apply. #### Returns | Type | Description | | --- | --- | | `{Command}` | the ordered command batch, which the caller owns | ### `failureOf` _function_ ```nupp function failureOf(image: integer): string? ``` Returns why the backend rejected one image. #### Arguments | Name | Type | Description | | --- | --- | --- | | `image` | `integer` | the process-wide image id | #### Returns | Type | Description | | --- | --- | | `string?` | the host failure reason, or nil unless the state is `"failed"` | ### `id` _function_ ```nupp function id(name: string): integer ``` Returns the permanent id one image name resolves to. Interning a name does not make it resident. A sprite may be built against an id whose pixels arrive later, or never. #### Arguments | Name | Type | Description | | --- | --- | --- | | `name` | `string` | the stable image name, which a snapshot stores | #### Returns | Type | Description | | --- | --- | | `integer` | the process-wide image id, which is always greater than zero | #### Raises - when the name is empty ### `load` _function_ ```nupp function load(path: string, name: string?): integer ``` Decodes a PNG or JPEG file and queues its RGBA pixels for upload. #### Arguments | Name | Type | Description | | --- | --- | --- | | `path` | `string` | the image file path | | `name` | `string?` | the stable image name; omitted uses the file path | #### Returns | Type | Description | | --- | --- | | `integer` | the image id, whose dimensions are immediately available | #### Raises - when the file cannot be decoded ### `nameOf` _function_ ```nupp function nameOf(image: integer): string? ``` Returns the name one image id was interned under. #### Arguments | Name | Type | Description | | --- | --- | --- | | `image` | `integer` | the process-wide image id | #### Returns | Type | Description | | --- | --- | | `string?` | the name, or nil when no image carries that id | ### `release` _function_ ```nupp function release(name: string): boolean, string? ``` Queues one image for release. The id survives the release, so a later `upload` under the same name makes the same id resident again. Sprites pointing at a released image draw the backend's fallback until then. #### Arguments | Name | Type | Description | | --- | --- | --- | | `name` | `string` | the stable image name | #### Returns | Type | Description | | --- | --- | | `boolean` | whether a release was queued, which is false for a name nothing uploaded | | `string?` | why nothing was queued, when unsuccessful | ### `residencyRevision` _function_ ```nupp function residencyRevision(): integer ``` Returns the revision of image residency and sampling metadata. #### Returns | Type | Description | | --- | --- | | `integer` | A monotonic count that changes when residency or sampling changes. | ### `samplerIndex` _function_ ```nupp function samplerIndex(filter: Filter?, address: Address?): integer ``` Returns the sampler index one filter and address mode select. #### Arguments | Name | Type | Description | | --- | --- | --- | | `filter` | `Filter?` | the filtering mode, defaulting to `"nearest"` | | `address` | `Address?` | the addressing mode, defaulting to `"clamp"` | #### Returns | Type | Description | | --- | --- | | `integer` | the sampler index, from zero to `SAMPLER_COUNT` minus one | #### Raises - when either mode is not one of its declared values ### `samplerOf` _function_ ```nupp function samplerOf(image: integer): integer ``` Returns the sampler index extraction writes for one image. #### Arguments | Name | Type | Description | | --- | --- | --- | | `image` | `integer` | the process-wide image id | #### Returns | Type | Description | | --- | --- | | `integer` | the sampler index, which is nearest filtering with clamped edges for an unknown id | ### `setMaterialMaps` _function_ ```nupp function setMaterialMaps(image: integer, maps: MaterialMaps): nil ``` Associates normal, emission and packed occlusion/roughness/metallic images. All supplied maps must have the albedo image dimensions. Applies to sprites and TileChunks using that image; replacement pixels keep the association. #### Arguments | Name | Type | Description | | --- | --- | --- | | `image` | `integer` | | | `maps` | `MaterialMaps` | | #### Returns | Type | Description | | --- | --- | | `nil` | | ### `sizeOf` _function_ ```nupp function sizeOf(image: integer): integer, integer ``` Returns the texel dimensions the last accepted upload declared. #### Arguments | Name | Type | Description | | --- | --- | --- | | `image` | `integer` | the process-wide image id | #### Returns | Type | Description | | --- | --- | | `integer` | the width and then the height in texels, both zero before an upload | | `integer` | | ### `stateOf` _function_ ```nupp function stateOf(image: integer): State ``` Returns where one image stands with the backend. #### Arguments | Name | Type | Description | | --- | --- | --- | | `image` | `integer` | the process-wide image id | #### Returns | Type | Description | | --- | --- | | `State` | the residency state, which is `"unknown"` for an id nothing uploaded | ### `upload` _function_ ```nupp function upload(options: UploadOptions): integer ``` Queues one image for residency and returns its permanent id. Uploading a name that is already resident replaces its pixels behind the same id, so every sprite pointing at it draws the new image once the host reports the replacement complete. #### Arguments | Name | Type | Description | | --- | --- | --- | | `options` | `UploadOptions` | the name, texel dimensions, RGBA8 pixels, and sampling modes | #### Returns | Type | Description | | --- | --- | | `integer` | the process-wide image id | #### Raises - when the name is empty, a dimension is not positive, a sampling mode is unknown, or the pixel length is not four bytes per texel ## Values ### `SAMPLER_COUNT` _variable_ ```nupp const SAMPLER_COUNT: integer ``` The number of distinct samplers a backend must create. Every filter paired with every address mode, so a sampler is selected by index and never created on demand.