-
Notifications
You must be signed in to change notification settings - Fork 342
Description
Motivation
Today GPUBindGroupLayout and GPUPipelineLayout are the most complicated part of the API. How about we add some defaults to them?
Namely it would change this sample code:
const bindGroupLayout = device.createBindGroupLayout({
bindings: [
{binding: 0, visibility: GPUShaderStage.COMPUTE, type: "storage-buffer"},
{binding: 1, visibility: GPUShaderStage.COMPUTE, type: "storage-buffer"},
{binding: 2, visibility: GPUShaderStage.COMPUTE, type: "storage-buffer"}
]
});
const bindGroup = device.createBindGroup({
layout: bindGroupLayout,
bindings: [
{binding: 0, resource: {buffer: gpuBufferFirstMatrix}},
{binding: 1, resource: {buffer: gpuBufferSecondMatrix}},
{binding: 2, resource: {buffer: resultMatrixBuffer}}
]
});
const computeShaderCode = `#version 450
layout(std430, set = 0, binding = 0) readonly buffer FirstMatrix {
} firstMatrix;
layout(std430, set = 0, binding = 1) readonly buffer SecondMatrix {
} secondMatrix;
layout(std430, set = 0, binding = 2) buffer ResultMatrix {
} resultMatrix;`;
const computePipeline = device.createComputePipeline({
layout: device.createPipelineLayout({
bindGroupLayouts: [bindGroupLayout]
}),
computeStage: {
module: device.createShaderModule({code: theCode}),
entryPoint: "main"
}
});into
const bindGroup = device.createBindGroup({
bindings: [
{binding: 0, resource: {buffer: gpuBufferFirstMatrix}},
{binding: 1, resource: {buffer: gpuBufferSecondMatrix}},
{binding: 2, resource: {buffer: resultMatrixBuffer}}
]
});
const computeShaderCode = `#version 450
layout(std430, set = 0, binding = 0) readonly buffer FirstMatrix {
} firstMatrix;
layout(std430, set = 0, binding = 1) readonly buffer SecondMatrix {
} secondMatrix;
layout(std430, set = 0, binding = 2) buffer ResultMatrix {
} resultMatrix;`;
const computePipeline = device.createComputePipeline({
computeStage: {
module: device.createShaderModule({code: theCode}),
entryPoint: "main"
}
});which is much easier to understand for people getting started with WebGPU, and almost 50% less code to type for experienced WebGPU developers hacking with the API.
How would this work
It makes the layout member of GPUPipelineDescriptorBase and GPUBindGroupDescriptor optional and if not present deduces them using the following algorithms.
For GPUBindGroupDescriptor it implicitly creates a GPUBindGroupLayout that one binding (with the same binding number) for each binding in the GPUBindGroupDescriptor. visibility is always all the stage and other member are set like so (if not described, they get their default value):
- If the
resourceis aGPUSampler,typeis"sampler" - If the
resourceis aGPUTextureView, if the texture has not exactly one of theSAMPLEDandSTORAGEusages, an error is produced.typeis"sampled-texture"if the texture has theSAMPLEDusage,"storage-texture"otherwise.textureDimensionis set to the texture view dimension of the view, andtextureComponentTypeset to the component type of the texture's format. If the texture has asampleCountlarger than 1,multisampledis set sotrue. - If the
resourceis aGPUBufferBinding, if the buffer has not exactly one of theUNIFORMandSTORAGEusages, an error is produced.typeis"uniform-buffer"if the buffer has theUNIFORMusage,"storage-buffer"otherwise.
For GPUComputePipeline and GPURenderPipeline we would deduce an implicit GPUPipelineLayout that has implicit GPUBindGroupLayouts for each set used by the pipeline. visibility is set to all shader stages. Then for each binding of the shader modules of the pipeline a binding is inserted in the correct GPUBindGroupLayout with the matching binding like the following (members not mentioned get their default value):
- For sampler bindings in the shadermodule,
typeis set to"sampler". - For uniform buffer bindings,
typeis set to"uniform-buffer". - For storage buffer bindings,
typeis set to"storage-buffer". - For texture bindings, if the texture (SPIRV-ism) has the Sampled bit set to 0,
typeis set tostorage-texture,sampled-textureotherwise.textureViewDimensionis set to match the texture binding declaration, as ismultisampledandtextureComponentType.
Note that for render pipeline this would also require checking no two bindings conflict.