Signatur
Beschreibung
writeTexture() ist der einfachste Weg, CPU-seitige Rohdaten in eine WebGPU-Textur zu laden: Texturatlanten, prozedural erzeugte Muster, Lookup-Tabellen, Heightmaps oder Pixel aus getImageData(). Sie brauchen dafür keinen Zwischenpuffer (GPUBuffer) und keinen Command-Encoder, denn die Methode reiht die Kopie direkt in die Warteschlange (device.queue) ein.
Die Daten werden beim Aufruf sofort kopiert. Danach können Sie den Quellpuffer also gleich wiederverwenden oder verändern. Ausgeführt wird der Schreibvorgang auf der GPU in Reihenfolge mit den übrigen Arbeiten der Warteschlange, also vor allen Befehlspuffern, die Sie später mit queue.submit() einreichen.
Das Speicherlayout der Quelldaten legen Sie mit dataLayout fest. bytesPerRow gibt an, wie viele Bytes zwischen dem Anfang zweier Pixelzeilen liegen. Bei rgba8unorm sind das zum Beispiel breite * 4. Anders als bei copyBufferToTexture() muss bytesPerRow hier kein Vielfaches von 256 sein.
Für Bilder, die schon im Browser vorliegen (ImageBitmap, HTMLCanvasElement, VideoFrame), ist copyExternalImageToTexture() meist die bessere Wahl. Damit entfällt das Auslesen der Pixel auf der CPU.
Parameter
| Name | Typ | Default | Beschreibung |
|---|---|---|---|
| $destination Pflicht | GPUTexelCopyTextureInfo (Objekt) | Das Ziel der Kopie. Enthält texture (die GPUTexture, Pflicht), mipLevel (Standard 0), origin (Startpunkt als {x, y, z} oder Array, Standard {x: 0, y: 0, z: 0}) und aspect ("all", "depth-only" oder "stencil-only", Standard "all"). |
|
| $data Pflicht | ArrayBuffer | TypedArray | DataView | SharedArrayBuffer | Die Quelldaten mit den Texeln im Format der Zieltextur. | |
| $dataLayout Pflicht | GPUTexelCopyBufferLayout (Objekt) | Das Layout der Quelldaten: offset (Start in Bytes innerhalb von data, Standard 0), bytesPerRow (Abstand zwischen zwei Zeilen bzw. Blockzeilen in Bytes; Pflicht, sobald mehr als eine Zeile kopiert wird) und rowsPerImage (Zeilen pro Ebene; Pflicht, wenn depthOrArrayLayers größer als 1 ist). |
|
| $size Pflicht | GPUExtent3D (Objekt | number[]) | Die Größe des zu schreibenden Bereichs als {width, height, depthOrArrayLayers} oder als Array [width, height, depth]. height und depthOrArrayLayers sind standardmäßig 1. |
Rückgabewert
GPUValidationError auf dem Gerät gemeldet.Beispiele
Schachbrett-Textur prozedural erzeugen und hochladen
const adapter = await navigator.gpu.requestAdapter();
const device = await adapter.requestDevice();
const size = 8;
const texture = device.createTexture({
size: [size, size],
format: 'rgba8unorm',
usage: GPUTextureUsage.TEXTURE_BINDING | GPUTextureUsage.COPY_DST,
});
// 8×8 Pixel, je 4 Bytes (RGBA)
const pixels = new Uint8Array(size * size * 4);
for (let y = 0; y < size; y++) {
for (let x = 0; x < size; x++) {
const i = (y * size + x) * 4;
const v = (x + y) % 2 === 0 ? 255 : 0;
pixels.set([v, v, v, 255], i);
}
}
device.queue.writeTexture(
{ texture },
pixels,
{ bytesPerRow: size * 4 }, // kein 256er-Alignment nötig
{ width: size, height: size },
);
console.log('Textur geschrieben:', texture.width, 'x', texture.height);
Pixel aus einem 2D-Canvas übernehmen
const canvas = new OffscreenCanvas(64, 64);
const ctx = canvas.getContext('2d');
ctx.fillStyle = 'tomato';
ctx.fillRect(0, 0, 64, 64);
ctx.fillStyle = 'white';
ctx.fillText('GPU', 20, 36);
const { data, width, height } = ctx.getImageData(0, 0, 64, 64);
const adapter = await navigator.gpu.requestAdapter();
const device = await adapter.requestDevice();
const texture = device.createTexture({
size: [width, height],
format: 'rgba8unorm',
usage: GPUTextureUsage.TEXTURE_BINDING | GPUTextureUsage.COPY_DST,
});
// data ist ein Uint8ClampedArray, also ein gültiges TypedArray
device.queue.writeTexture({ texture }, data, { bytesPerRow: width * 4 }, [width, height]);
Teilbereich einer Mip-Stufe aktualisieren, mit Fehlerprüfung
const adapter = await navigator.gpu.requestAdapter();
const device = await adapter.requestDevice();
const texture = device.createTexture({
size: [256, 256],
mipLevelCount: 2,
format: 'r32float',
usage: GPUTextureUsage.TEXTURE_BINDING | GPUTextureUsage.COPY_DST,
});
// Ein 16×16-Block mit Float-Werten, beginnt 4 Floats (16 Bytes) im Puffer
const block = new Float32Array(4 + 16 * 16).fill(0.5);
device.pushErrorScope('validation');
device.queue.writeTexture(
{ texture, mipLevel: 1, origin: { x: 32, y: 32 } }, // Mip 1 ist 128×128
block,
{ offset: 16, bytesPerRow: 16 * 4 },
{ width: 16, height: 16 },
);
const error = await device.popErrorScope();
console.log(error ? `Fehler: ${error.message}` : 'Upload OK');