简体   繁体   中英

Why can I only have a single Texture binding in my wgpu bind group?

I currently have a BindGroup and BindGroupLayout which looks like this:

let bind_group_layout = device.create_bind_group_layout(&wgpu::BindGroupLayoutDescriptor {
    label: None,
    entries: &[wgpu::BindGroupLayoutEntry {
        binding: 0,
        visibility: wgpu::ShaderStages::FRAGMENT,
        ty: wgpu::BindingType::Texture {
            sample_type: wgpu::TextureSampleType::Float { filterable: true },
            view_dimension: wgpu::TextureViewDimension::D2,
            multisampled: false,
        },
        count: None,
    }],
});

let bind_group = device.create_bind_group(&wgpu::BindGroupDescriptor {
    label: None,
    entries: &[wgpu::BindGroupEntry {
        binding: 0,
        resource: wgpu::BindingResource::TextureView(&target),
    }],
    layout: &bind_group_layout,
});

and works as desired.

For context: I use these in a render pass to do post-processing.

Now I also needed a Sampler in my shader. First I created the Sampler

let linear_sampler = device.create_sampler(&wgpu::SamplerDescriptor {
    mag_filter: wgpu::FilterMode::Nearest,
    min_filter: wgpu::FilterMode::Nearest,
    mipmap_filter: wgpu::FilterMode::Nearest,
    ..Default::default()
});

and added it to the layout and bind group like so:

let bind_group_layout = device.create_bind_group_layout(&wgpu::BindGroupLayoutDescriptor {
    label: None,
    entries: &[
        wgpu::BindGroupLayoutEntry {
            binding: 0,
            visibility: wgpu::ShaderStages::FRAGMENT,
            ty: wgpu::BindingType::Texture {
                sample_type: wgpu::TextureSampleType::Float { filterable: true },
                view_dimension: wgpu::TextureViewDimension::D2,
                multisampled: false,
            },
            count: None,
        },
        wgpu::BindGroupLayoutEntry {
            binding: 1,
            visibility: wgpu::ShaderStages::FRAGMENT,
            ty: wgpu::BindingType::Sampler(wgpu::SamplerBindingType::NonFiltering),
            count: None,
        },
    ],
});

let bind_group = device.create_bind_group(&wgpu::BindGroupDescriptor {
    label: None,
    entries: &[
        wgpu::BindGroupEntry {
            binding: 0,
            resource: wgpu::BindingResource::TextureView(&target),
        },
        wgpu::BindGroupEntry {
            binding: 1,
            resource: wgpu::BindingResource::Sampler(&linear_sampler),
        },
    ],
    layout: &bind_group_layout,
});

However when I now run my code a get a ValidationError saying that:

thread 'main' panicked at 'wgpu error: Validation Error

Caused by:
    In a RenderPass
      note: encoder = `<CommandBuffer-(0, 2, Metal)>`
    In a draw command, indexed:false indirect:false
      note: render pipeline = `<RenderPipeline-(1, 1, Metal)>`
    the pipeline layout, associated with the current render pipeline, contains a bind group layout at index 0 which is incompatible with the bind group layout associated with the bind group at 0

I noticed the same behaviour on Metal and DirectX 12 . I also noticed that I get the same error when I only add one sampler or when I add two Texture Bindings as shown below:

let bind_group_layout = device.create_bind_group_layout(&wgpu::BindGroupLayoutDescriptor {
    label: None,
    entries: &[
        wgpu::BindGroupLayoutEntry {
            binding: 0,
            visibility: wgpu::ShaderStages::FRAGMENT,
            ty: wgpu::BindingType::Texture {
                sample_type: wgpu::TextureSampleType::Float { filterable: true },
                view_dimension: wgpu::TextureViewDimension::D2,
                multisampled: false,
            },
            count: None,
        },
        wgpu::BindGroupLayoutEntry {
            binding: 1,
            visibility: wgpu::ShaderStages::FRAGMENT,
            ty: wgpu::BindingType::Texture {
                sample_type: wgpu::TextureSampleType::Float { filterable: true },
                view_dimension: wgpu::TextureViewDimension::D2,
                multisampled: false,
            },
            count: None,
        },
    ],
});

let bind_group = device.create_bind_group(&wgpu::BindGroupDescriptor {
    label: None,
    entries: &[
        wgpu::BindGroupEntry {
            binding: 0,
            resource: wgpu::BindingResource::TextureView(&target),
        },
        wgpu::BindGroupEntry {
            binding: 1,
            resource: wgpu::BindingResource::TextureView(&target),
        },
    ],
    layout: &bind_group_layout,
});

So the only configuration I found to be working is when the bind group and layout contain exactly one texture binding.

Does anybody have an idea why this is the case here?

The full code can be found here . The failing code is in src/fxaa/ and can be tested using cargo run --example triangle , the original working code is in src/grayscale/ and can be run using cargo run --example text . I ommited the shaders for brevity and because their contents does not seem to matter, but they can also be found in the repo linked above.

Because in fn resize(&mut self, device: &wgpu::Device, size: &wgpu::Extent3d) , you have created a new bind_group that is incompatible with already binded bind_group_layout .

If you recreate a new bind_group_layout , you also need to recreate a new pipeline and pipeline_layout .

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM