Symbols in this topic
Texture
Texture is the core wrapper around a GPUTexture. Use it for explicit texture allocation through Device.createTexture(...), cached default views, resizing owned textures, readback, and wrapper-aware teardown.
Import
TypeScript
1
import { Texture } from "vgpu/core";Signature
TypeScript
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
import type { Device } from "vgpu/core";
type TextureUsageName = "copy_src" | "copy_dst" | "texture_binding" | "storage_binding" | "render_attachment";
interface TextureOptions {
readonly size: readonly [width: number, height: number, depthOrArrayLayers?: number];
readonly format: GPUTextureFormat;
readonly usage: readonly TextureUsageName[];
readonly mipLevelCount?: number;
readonly sampleCount?: 1 | 4;
readonly dimension?: GPUTextureDimension;
readonly viewFormats?: readonly GPUTextureFormat[];
readonly label?: string;
}
declare class Texture {
constructor(device: Device, gpu: GPUTexture, options: TextureOptions, ownership?: "owned" | "external");
get gpu(): GPUTexture;
get options(): TextureOptions;
get size(): TextureOptions["size"];
get format(): GPUTextureFormat;
get usage(): TextureOptions["usage"];
get mipLevelCount(): number;
get sampleCount(): 1 | 4;
get dimension(): GPUTextureDimension;
get viewFormats(): readonly GPUTextureFormat[];
get label(): string | undefined;
get view(): GPUTextureView;
createView(desc?: GPUTextureViewDescriptor): GPUTextureView;
resize(size: readonly [number, number] | readonly [number, number, number]): boolean;
read(): Promise<Uint8Array>;
readFloats(): Promise<Float32Array>;
destroy(): void;
dispose(): void;
}Parameters
Device.createTexture(opts) / TextureOptions
| Param | Type | Required | Default | Notes |
|---|---|---|---|---|
| opts.size | readonly [width: number, height: number, depthOrArrayLayers?: number] | ✔ | — | Stored as tuple and converted to { width, height, depthOrArrayLayers: opts.size[2] ?? 1 } for WebGPU. |
| opts.format | GPUTextureFormat | ✔ | — | Forwarded to GPUTextureDescriptor.format. read()/readFloats() support the color formats listed under Readback formats. |
| opts.usage | readonly TextureUsageName[] | ✔ | — | Vgpu usage names mapped to GPUTextureUsage flags. |
| opts.mipLevelCount | number | ✖ | WebGPU default (1) | Only included in the native descriptor when provided; getter returns opts.mipLevelCount ?? 1. |
| opts.sampleCount | 1 | 4 | ✖ | WebGPU default (1) | Only included when provided; getter returns opts.sampleCount ?? 1. Use 4 for MSAA where WebGPU allows it. |
| opts.dimension | GPUTextureDimension | ✖ | WebGPU default ("2d") | Only included when provided; getter returns opts.dimension ?? "2d". |
| opts.viewFormats | readonly GPUTextureFormat[] | ✖ | [] | Only included when provided; getter returns opts.viewFormats ?? []. |
| opts.label | string | ✖ | undefined | Forwarded to GPUTextureDescriptor.label and exposed via texture.label. |
Valid TextureUsageName values: "copy_src", "copy_dst", "texture_binding", "storage_binding", "render_attachment".
Constructor
| Param | Type | Required | Default | Notes |
|---|---|---|---|---|
| device | Device | ✔ | — | Owning device wrapper. Normally supplied by Device.createTexture(...). |
| gpu | GPUTexture | ✔ | — | Raw WebGPU texture. |
| options | TextureOptions | ✔ | — | Original vgpu descriptor exposed as texture.options. |
| ownership | "owned" | "external" | ✖ | "owned" | Owned textures can be resized and destroyed by the wrapper; external textures cannot be resized or destroyed by the wrapper. |
Views, resize, readback
| Param | Type | Required | Default | Notes |
|---|---|---|---|---|
| desc | GPUTextureViewDescriptor | ✖ | undefined | createView(desc?) forwards directly to gpu.createView(desc). |
| size | readonly [number, number] | readonly [number, number, number] | ✔ | — | New extent for resize(...). A 2-tuple preserves the current depth/array layers. |
Returns:
Device.createTexture(opts)returnsTexture.texture.viewreturns a cached defaultGPUTextureViewcreated with no descriptor.createView(desc?)returns a freshGPUTextureView.resize(size)returnsfalseif the extent is unchanged, otherwise reallocates the raw texture and returnstrue.read()returnsPromise<Uint8Array>with unpadded texel bytes in the texture's own format:byteLengthiswidth * height * bytesPerPixel(format)(4 forrgba8unorm, 8 forrgba16float, 16 forrgba32float, …).bgra*bytes are swizzled to RGBA order.readFloats()returnsPromise<Float32Array>with one f32 per component, row-major,width * height * components(format)long. Float formats keep their HDR values (no clamping to[0, 1]),unorm8formats are normalized by/ 255without srgb gamma conversion.destroy()anddispose()returnvoid.
Throws:
VGPU-CORE-TEXTURE-DESTROYEDwhenview,resize(...),read(), orreadFloats()is used afterdestroy()/dispose()— create a new texture instead.VGPU-CORE-EXTERNAL-TEXTUREwhenresize(...)is called on a texture constructed withownership: "external"— resize the owning canvas/swapchain/resource instead.VGPU-CORE-TEXTURE-RESIZE-LOCKEDwhen an internal resize lock is active — follow the lock message and resize through the owner that installed the lock.VGPU-CORE-UNSUPPORTED-FORMATwhenread()/readFloats()is called on a format outside Readback formats (depth/stencil, packed, snorm/uint/sint, and compressed formats) — blit into a supported format first, or read the data through a storage buffer.- Native WebGPU validation errors may occur for invalid size/format/usage combinations.
Examples
TypeScript
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
import { createMockAdapter } from "vgpu/mock";
const device = await createMockAdapter().requestDevice();
const target = device.createTexture({
label: "offscreen-target",
size: [4, 4],
format: "rgba8unorm",
usage: ["render_attachment", "texture_binding", "copy_src"],
});
const defaultView = target.view;
const explicitView = target.createView({ label: "offscreen-target.view" });
console.log(defaultView, explicitView, target.sampleCount); // sampleCount defaults to 1
device.destroy();TypeScript
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
import { createMockAdapter } from "vgpu/mock";
const device = await createMockAdapter().requestDevice();
const texture = device.createTexture({
size: [1, 1, 6],
format: "rgba8unorm",
usage: ["texture_binding", "copy_src"],
});
console.log(texture.resize([2, 2])); // true; depthOrArrayLayers stays 6
console.log(texture.size); // [2, 2, 6]
console.log(texture.resize([2, 2, 6])); // false; unchanged
const pixels = await texture.read();
console.log(pixels.byteLength); // width * height * 4
device.destroy();TypeScript
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
import { createMockAdapter } from "vgpu/mock";
const device = await createMockAdapter().requestDevice();
const hdr = device.createTexture({
size: [2, 2],
format: "rgba16float",
usage: ["render_attachment", "copy_src"],
});
const bytes = await hdr.read();
console.log(bytes.byteLength); // 2 * 2 * 8 — raw half-float bytes
const floats = await hdr.readFloats();
console.log(floats.length); // 2 * 2 * 4 — decoded rgba components, values may exceed 1
device.destroy();Readback formats
| Format | Bytes per texel | Components | readFloats() decoding |
|---|---|---|---|
r8unorm | 1 | 1 | byte / 255 |
rg8unorm | 2 | 2 | byte / 255 |
rgba8unorm, rgba8unorm-srgb | 4 | 4 | byte / 255 (no srgb gamma conversion) |
bgra8unorm, bgra8unorm-srgb | 4 | 4 | byte / 255, channels swizzled to RGBA |
r16float | 2 | 1 | binary16 widened to f32 |
rg16float | 4 | 2 | binary16 widened to f32 |
rgba16float | 8 | 4 | binary16 widened to f32 |
r32float | 4 | 1 | verbatim f32 |
rg32float | 8 | 2 | verbatim f32 |
rgba32float | 16 | 4 | verbatim f32 |
Subnormals, infinities, and NaN survive the binary16 → f32 widening unchanged.
Notes
texture.viewis cached and descriptorless. UsecreateView(descriptor)for mip, array-layer, cube, or format-specific views.resize(...)preserves all descriptor fields exceptsize; contents are not preserved. Rebuild bind groups or caches keyed bytexture.gpuafter a resize.- Prefer
texture.destroy()/texture.dispose()overtexture.gpu.destroy()so the wrapper invalidates cached views and emits lifecycle state correctly. - Include
"copy_src"when you plan to callread()/readFloats()on real WebGPU devices; mock textures can still expose their mock bytes. - Prefer
readFloats()for HDR textures (rgba16float,rgba32float):read()hands back the raw half/float bytes, which are only useful after a decode.read()remains the right call forrgba8unormsnapshots and PNG encoding. - See also:
Device,Buffer,Queue,cubeView,layerView.