Start · Sprachen · JavaScript · Referenz · GPUQueue.writeTexture()

GPUQueue.writeTexture()

Methode

Schreibt Pixeldaten aus einem <code>ArrayBuffer</code>, <code>TypedArray</code> oder <code>DataView</code> direkt in einen Bereich einer <code>GPUTexture</code>.

seit JavaScript WebGPU: Chrome/Edge 113+, Safari 26+, Firefox 141+ Kategorie: webapi

Signatur

GPUQueue.prototype.writeTexture(destination, data, dataLayout, size)

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

Typ
undefined
Beschreibung
Kein Rückgabewert. Der Schreibvorgang wird nur eingereiht. Validierungsfehler werden nicht als Ausnahme geworfen, sondern als 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);
Textur geschrieben: 8 x 8

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');
Upload OK