gfx-rs / gfx

[maintenance mode] A low-overhead Vulkan-like GPU API for Rust.
http://gfx-rs.github.io/
Apache License 2.0
5.35k stars 548 forks source link

Metal descriptor set write spill is broken #1968

Open zakarumych opened 6 years ago

zakarumych commented 6 years ago

As this note stated descriptors must be bound to following bindings when there are more provided than array count of the binding point. Yet this is true only for Vulkan backend currently. This could be a problem for portability.

msiglreith commented 6 years ago

dx12 and metal are doing this as well iirc. I think @kvark implemented it some time ago

kvark commented 6 years ago

I do recall actually covering this case. @omni-viral do you see the logic missing in D3D12/metal at the moment?

zakarumych commented 6 years ago

Yes. It doesn't work on metal. I'll recheck

zakarumych commented 6 years ago

I confim. On metal.

This code works.

factory.write_descriptor_sets(
    once(DescriptorSetWrite {
        set: &set,
        binding: 0,
        array_offset: 0,
        descriptors: Some(Descriptor::Buffer(buffer.borrow(), Some(tilemap_uniform_range.start) .. Some(tilemap_uniform_range.end))),
    }).chain(once(DescriptorSetWrite {
        set: &set,
        binding: 1,
        array_offset: 0,
        descriptors: Some(Descriptor::Buffer(buffer.borrow(), Some(transform_uniform_range.start) .. Some(transform_uniform_range.end))),
    })).chain(once(DescriptorSetWrite {
        set: &set,
        binding: 2,
        array_offset: 0,
        descriptors: Some(Descriptor::Sampler(&self.sampler)),
    })).chain(once(DescriptorSetWrite {
        set: &set,
        binding: 3,
        array_offset: 0,
        descriptors: Some(Descriptor::Image(self.tileset.view(), Layout::ShaderReadOnlyOptimal)),
    }))
);

This segfaults

factory.write_descriptor_sets(
    once(DescriptorSetWrite {
        set: &set,
        binding: 0,
        array_offset: 0,
        descriptors: &[
            Descriptor::Buffer(buffer.borrow(), Some(tilemap_uniform_range.start) .. Some(tilemap_uniform_range.end)),
            Descriptor::Buffer(buffer.borrow(), Some(transform_uniform_range.start) .. Some(transform_uniform_range.end)),
            Descriptor::Sampler(&self.sampler),
            Descriptor::Image(self.tileset.view(), Layout::ShaderReadOnlyOptimal),
        ],
    })
);