Signatur
Beschreibung
createTexture() legt auf einem GPUDevice eine neue Textur an, also einen strukturierten Speicherbereich auf der GPU. In diese Textur lassen sich Bilddaten hochladen (GPUQueue.writeTexture(), copyExternalImageToTexture()), sie kann als Render-Ziel (Farb- oder Tiefenanhang) dienen und in Shadern gesampelt oder als Storage-Textur beschrieben werden.
Der Deskriptor legt Größe, Format, Dimension, Mip-Level-Anzahl, Multisampling und – ganz wichtig – die erlaubten Verwendungszwecke (usage) fest. Diese Eigenschaften sind unveränderlich: Wer später eine andere Größe (z. B. nach einem Fenster-Resize) oder ein anderes Format braucht, muss eine neue Textur erstellen und die alte mit destroy() freigeben.
Die Methode arbeitet synchron und gibt sofort ein GPUTexture-Objekt zurück. Ungültige Deskriptoren werfen normalerweise keine Ausnahme, sondern erzeugen einen Validierungsfehler und eine ungültige Textur. Solche Fehler fängt man mit device.pushErrorScope("validation") / popErrorScope() oder über das Ereignis uncapturederror ab.
Parameter
| Name | Typ | Default | Beschreibung |
|---|---|---|---|
| $descriptor Pflicht | GPUTextureDescriptor | Konfigurationsobjekt mit den unten aufgeführten Eigenschaften. | |
| $descriptor.size Pflicht | GPUExtent3D (Array | {width, height?, depthOrArrayLayers?}) | Größe in Texeln, z. B. [512, 512] oder { width: 512, height: 512, depthOrArrayLayers: 6 }. Nicht angegebene Werte für height/depthOrArrayLayers sind 1. |
|
| $descriptor.format Pflicht | GPUTextureFormat (string) | Texelformat, z. B. "rgba8unorm", "bgra8unorm", "depth24plus", "rgba16float". |
|
| $descriptor.usage Pflicht | number (GPUTextureUsageFlags) | Bitmaske aus GPUTextureUsage.COPY_SRC, COPY_DST, TEXTURE_BINDING, STORAGE_BINDING, RENDER_ATTACHMENT, mit | verknüpft. |
|
| $descriptor.dimension | "1d" | "2d" | "3d" | "2d" | Dimension der Textur. |
| $descriptor.mipLevelCount | number | 1 | Anzahl der Mip-Level. Maximal floor(log2(max(width, height))) + 1. |
| $descriptor.sampleCount | number | 1 | Anzahl der Samples pro Texel; 1 oder 4 (Multisampling). Bei 4 muss mipLevelCount 1 sein, und STORAGE_BINDING ist nicht erlaubt. |
| $descriptor.viewFormats | Array<GPUTextureFormat> | [] | Weitere Formate, die für createView() erlaubt sind, z. B. ["rgba8unorm-srgb"] für eine rgba8unorm-Textur. Erlaubt sind nur Formate, die sich lediglich in sRGB/linear unterscheiden. |
| $descriptor.textureBindingViewDimension | GPUTextureViewDimension | Nur für Kompatibilitätsmodus: legt die View-Dimension (z. B. "cube") bei der Bindung fest. |
|
| $descriptor.label | string | "" | Name zur Fehlersuche; erscheint in Fehlermeldungen und Debug-Werkzeugen. |
Rückgabewert
Beispiele
Bild laden und als Textur hochladen
const adapter = await navigator.gpu.requestAdapter();
const device = await adapter.requestDevice();
const response = await fetch('/img/logo.png');
const bitmap = await createImageBitmap(await response.blob());
const texture = device.createTexture({
label: 'Logo-Textur',
size: [bitmap.width, bitmap.height],
format: 'rgba8unorm',
usage: GPUTextureUsage.TEXTURE_BINDING |
GPUTextureUsage.COPY_DST |
GPUTextureUsage.RENDER_ATTACHMENT // für copyExternalImageToTexture nötig
});
device.queue.copyExternalImageToTexture(
{ source: bitmap },
{ texture },
[bitmap.width, bitmap.height]
);
console.log(texture.width, texture.height, texture.format);
Tiefenpuffer für eine Render-Pass-Konfiguration
const canvas = document.querySelector('canvas');
const context = canvas.getContext('webgpu');
const depthTexture = device.createTexture({
label: 'Tiefenpuffer',
size: [canvas.width, canvas.height],
format: 'depth24plus',
usage: GPUTextureUsage.RENDER_ATTACHMENT
});
const encoder = device.createCommandEncoder();
const pass = encoder.beginRenderPass({
colorAttachments: [{
view: context.getCurrentTexture().createView(),
clearValue: { r: 0, g: 0, b: 0, a: 1 },
loadOp: 'clear',
storeOp: 'store'
}],
depthStencilAttachment: {
view: depthTexture.createView(),
depthClearValue: 1.0,
depthLoadOp: 'clear',
depthStoreOp: 'store'
}
});
pass.end();
device.queue.submit([encoder.finish()]);
Pixeldaten schreiben und Validierungsfehler abfangen
device.pushErrorScope('validation');
const size = 4;
const tex = device.createTexture({
size: [size, size],
format: 'rgba8unorm',
mipLevelCount: 3, // max. floor(log2(4)) + 1 = 3
usage: GPUTextureUsage.TEXTURE_BINDING | GPUTextureUsage.COPY_DST
});
// Schachbrettmuster für Mip-Level 0
const data = new Uint8Array(size * size * 4);
for (let i = 0; i < size * size; i++) {
const v = ((i % size) + Math.floor(i / size)) % 2 ? 255 : 0;
data.set([v, v, v, 255], i * 4);
}
device.queue.writeTexture(
{ texture: tex },
data,
{ bytesPerRow: size * 4 },
[size, size]
);
const error = await device.popErrorScope();
console.log(error ? `Fehler: ${error.message}` : 'Textur OK', tex.mipLevelCount);
// Wichtig · Fallstricke
- Keine Ausnahme bei Fehlern: Falsche Formate, zu große Abmessungen (über
device.limits.maxTextureDimension2D, oft 8192) oder zu viele Mip-Level erzeugen nur einen Validierungsfehler. Deshalb Error-Scopes verwenden oderlabelsetzen, damit sich Fehler leichter finden lassen. usageist unveränderlich: Fehlt z. B.COPY_DST, schlägtwriteTexture()fehl.copyExternalImageToTexture()braucht zusätzlichRENDER_ATTACHMENT.- Speicher freigeben: Texturen belegen GPU-Speicher. Nicht mehr benötigte Texturen, etwa nach einem Canvas-Resize, sollte man mit
texture.destroy()sofort freigeben, statt auf die Speicherbereinigung zu warten. - Formate: Manche Formate brauchen Features, z. B.
texture-compression-bcfür BC-Formate oderfloat32-filterable, die beirequestDevice()angefordert werden müssen. Für Canvas-Ziele liefertnavigator.gpu.getPreferredCanvasFormat()das passende Format. writeTexture: Hier mussbytesPerRownicht auf 256 aufgerundet werden, beicopyBufferToTexture()dagegen schon.- Kompatibilität: WebGPU ist nur in sicheren Kontexten verfügbar und noch nicht in allen Browsern bzw. auf allen Plattformen aktiviert. Vorher mit
if (!navigator.gpu)prüfen.