这是indexloc提供的服务,不要输入任何密码
Skip to content

Compat: maxStorage(Buffers/Textures)In(Vertex/Fragment)Stage should be more like maxStorage(Buffers/Textures)PerShaderStage? #5033

@greggman

Description

@greggman

I was implementing these in Chrome. My first implementation counts resources by checking bindGroupLayouts when creating pipelines. I ran into this issue. In the CTS there is a test that creates a bindGroupLayout with a storage texture. It then uses that with a shader that doesn't access the texture.

Example:

// passes because even though this device supports 0 storageTextures in fragment shaders
// the proposal is the error happens at create pipeline time
const bindGroupLayout = device.createBindGroupLayout({
  entries: [
    {
      binding: 0,
      visibility: GPUShaderStage.FRAGMENT,
      storageTexture: {
        access: "read-only",
        viewDimension: "2d",
        format: "rgba8unorm",
      },
    },
  ],
});

// passes because even though this device supports 0 storageTextures in fragment shaders
// the proposal is the error happens at create pipeline time
const pipelineLayout = device.createPipelineLayout({
  bindGroupLayouts: [ bindGroupLayout ],
});

// shader does not reference any resources
const module = device.createShaderModule({
  code: `
    @vertex fn vs() -> @builtin(position) vec4f { return vec4f(0); }
    @fragment fn fs() -> @location(0) vec4f { return vec4f(0); }
  `,
});

// failed in my impl because pipelineLayout uses a storage texture and device supports 0
const pipeline = device.createRenderPipeline({
  layout: pipelineLayout,
  vertex: { module },
  fragment: { module, targets: [{ format: 'rgba8unorm' }] },
});

Issue 1: This is different than the way maxStorage(Buffer/Texture)sPerShadeStage behaves

Change the code above so that it creates 5 storage texture bindings in createBindGroupLayout and it will get an error (5 > maxStorageTexturesPerShaderStage which is 4). Change the code above to make 2 bindGroupLayouts that each use 3 storage texture bindings. Those pass. Then try to create a pipelineLayout with both bindGroupLayouts. You'll get an error (6 > maxStorageTexturesPerShaderStage which is 4)

Issue 2: In both cases this is pessimizing (not sure that's the right word here)

Looking at the example code above, the shaders themselves don't actually use the resources so even though the "bindings" are past the limits the shaders aren't using them. You can't do this with maxStorageTexturesPerShaderStage because of the extra validation at createBindGroupLayout and createPipelineLayout

Question: Should we

  1. make the validation for maxStorage(Buffers/Textures)In(Vertex/Fragment)Stage similar to the validation for maxStorage(Buffer/Texture)sPerShadeStage so they are checked in createBindGroupLayout and createPipelineLayout?

  2. relax both compat and core so it's valid to make bindGroupLayouts and pipelineLayouts with more than maxStorage(Buffer/Texture)sPerShadeStage but you only get the error when you actually try to create a pipeline?

  3. Same as (2) but relax even more that you don't get an error at create pipeline time if the shaders themselves don't use more resources than allowed. I assume this was discussed long ago and there's a reason it's the way it is but I thought I'd ask since this came up in the context of a shader like the one above that uses no resources but getting an error because its pipeline layout referenced too many of a certain type of resource.

  4. Leave it as specified maxStorage(Buffers/Textures)In(Vertex/Fragment)Stage are not checked at createBindGroupLayout nor createPipelineLayout.

  5. other ideas...

What's the actual error

Further, If the choice is (4) there's the issue about what the actual error condition is. The current proposal for compat says simply:

If the number of shader variables of type texture_storage_1d, texture_storage_2d, texture_storage_2d_array and texture_storage_3d in a fragment shader exceeds the maxStorageTexturesInFragmentStage limit, a validation error will occur at pipeline creation time.

It does not spell out if this is what's in the pipeline layout or only what that shader actually uses.

Metadata

Metadata

Assignees

No one assigned

    Labels

    apiWebGPU APIcompatWebGPU Compatibility Mode

    Type

    No type

    Projects

    No projects

    Milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions