Signatur
Beschreibung
Die Eigenschaft sampleCount einer GPUTexture gibt die Anzahl der Samples pro Texel zurück. Der Wert entspricht dem Feld sampleCount des Deskriptors, der beim Erzeugen der Textur an GPUDevice.createTexture() übergeben wurde. Fehlt das Feld dort, ist der Standardwert 1.
Wichtig ist der Wert beim Multisample-Anti-Aliasing (MSAA). Eine Textur mit sampleCount: 4 speichert pro Pixel vier Farb- bzw. Tiefenwerte. Nach dem Rendern werden diese über ein resolveTarget in eine normale Textur mit einem Sample zusammengeführt. WebGPU erlaubt derzeit nur die Werte 1 und 4.
Nützlich ist die Eigenschaft vor allem in generischem Code, etwa in Render-Graphen, Hilfsfunktionen oder Debug-Werkzeugen. Dort kommen Texturen oft von außen, und man muss prüfen, ob sie zu einer Pipeline passen. Der multisample.count der Render-Pipeline muss nämlich mit dem sampleCount aller Farb- und Tiefen-Anhänge im Render-Pass übereinstimmen.
Rückgabewert
GPUSize32Out): 1 bei einer normalen Textur, 4 bei einer Multisample-Textur.Beispiele
sampleCount einer normalen und einer MSAA-Textur auslesen
const adapter = await navigator.gpu?.requestAdapter();
if (!adapter) throw new Error('WebGPU nicht verfügbar');
const device = await adapter.requestDevice();
const normal = device.createTexture({
size: [256, 256],
format: 'rgba8unorm',
usage: GPUTextureUsage.TEXTURE_BINDING
});
const msaa = device.createTexture({
size: [256, 256],
format: 'rgba8unorm',
sampleCount: 4,
usage: GPUTextureUsage.RENDER_ATTACHMENT
});
console.log(normal.sampleCount);
console.log(msaa.sampleCount);
MSAA-Render-Pass mit passender Pipeline und Resolve-Ziel
const canvas = document.querySelector('canvas');
const adapter = await navigator.gpu.requestAdapter();
const device = await adapter.requestDevice();
const context = canvas.getContext('webgpu');
const format = navigator.gpu.getPreferredCanvasFormat();
context.configure({ device, format });
const msaaTexture = device.createTexture({
size: [canvas.width, canvas.height],
format,
sampleCount: 4,
usage: GPUTextureUsage.RENDER_ATTACHMENT
});
const module = device.createShaderModule({ code: `
@vertex fn vs(@builtin(vertex_index) i: u32) -> @builtin(position) vec4f {
var p = array(vec2f(0, 0.5), vec2f(-0.5, -0.5), vec2f(0.5, -0.5));
return vec4f(p[i], 0, 1);
}
@fragment fn fs() -> @location(0) vec4f { return vec4f(1, 0.4, 0, 1); }
`});
// Die Pipeline übernimmt den sampleCount der Textur
const pipeline = device.createRenderPipeline({
layout: 'auto',
vertex: { module, entryPoint: 'vs' },
fragment: { module, entryPoint: 'fs', targets: [{ format }] },
multisample: { count: msaaTexture.sampleCount }
});
const encoder = device.createCommandEncoder();
const pass = encoder.beginRenderPass({
colorAttachments: [{
view: msaaTexture.createView(),
resolveTarget: context.getCurrentTexture().createView(),
loadOp: 'clear',
clearValue: [0, 0, 0, 1],
storeOp: 'discard'
}]
});
pass.setPipeline(pipeline);
pass.draw(3);
pass.end();
device.queue.submit([encoder.finish()]);
Hilfsfunktion: Anhänge vor dem Render-Pass prüfen
const assertMatchingSamples = (pipelineCount, ...textures) => {
for (const tex of textures) {
if (tex.sampleCount !== pipelineCount) {
throw new Error(
`Textur "${tex.label}" hat sampleCount ${tex.sampleCount}, Pipeline erwartet ${pipelineCount}`
);
}
}
};
const adapter = await navigator.gpu.requestAdapter();
const device = await adapter.requestDevice();
const color = device.createTexture({
label: 'Farbe', size: [640, 480], format: 'rgba8unorm',
sampleCount: 4, usage: GPUTextureUsage.RENDER_ATTACHMENT
});
const depth = device.createTexture({
label: 'Tiefe', size: [640, 480], format: 'depth24plus',
usage: GPUTextureUsage.RENDER_ATTACHMENT // sampleCount fehlt → 1
});
try {
assertMatchingSamples(4, color, depth);
} catch (e) {
console.warn(e.message);
}
// Wichtig · Fallstricke
- Schreibgeschützt: Den Wert kann man nach dem Erzeugen nicht mehr ändern. Eine Zuweisung wird ignoriert bzw. löst im Strict Mode einen
TypeErroraus. Wer einen anderen Wert braucht, muss eine neue Textur anlegen. - Nur 1 oder 4: Andere Werte wie
2oder8führen beicreateTexture()zu einem Validierungsfehler. Außerdem muss das Format Multisampling unterstützen. Einige Formate, etwa vieler32float-Varianten, können ohne zusätzliches Feature nicht aufgelöst werden. - Einschränkungen bei Multisample-Texturen: Sie müssen
dimension: '2d',mipLevelCount: 1und einRENDER_ATTACHMENT-Usage haben.STORAGE_BINDINGist nicht erlaubt. In WGSL liest man sie alstexture_multisampled_2d. - Canvas-Texturen: Die Textur von
context.getCurrentTexture()hat immersampleCount1. Für MSAA braucht man deshalb eine eigene Multisample-Textur, die perresolveTargetin die Canvas-Textur aufgelöst wird. - Speicher: Eine Textur mit 4 Samples belegt ungefähr viermal so viel Grafikspeicher.
storeOp: 'discard'auf der MSAA-Textur kann auf Tile-basierten GPUs Bandbreite sparen. - Kompatibilität: WebGPU gibt es nur in sicheren Kontexten und noch nicht überall. Die Unterstützung sollte man mit
navigator.gpuundrequestAdapter()prüfen.