ursus_core/vulkan/resources/
bindless.rs1use crate::render::gfx::descriptor::{DescriptorAllocator, DescriptorSetDesc};
2use crate::render::gfx::types::Format;
3use crate::render::gfx::types::{DescriptorSetId, ShaderStage};
4use crate::vulkan::core::{sampler, DeviceContext, SubmitContext};
5use crate::vulkan::resources::texture::TextureSource;
6use crate::vulkan::GpuTexture;
7use ash::vk;
8
9pub const MAX_TEXTURES: u32 = 4096;
10
11pub struct BindlessSet {
12 pub set_id: DescriptorSetId,
13 pub sampler: vk::Sampler,
14 next_slot: u32,
15 owned_textures: Vec<GpuTexture>,
16 device: ash::Device,
17}
18
19impl BindlessSet {
20 pub fn new(
21 device: &ash::Device,
22 physical_device: vk::PhysicalDevice,
23 instance: &ash::Instance,
24 descriptors: &mut DescriptorAllocator,
25 command_pool: vk::CommandPool,
26 queue: vk::Queue,
27 ) -> anyhow::Result<Self> {
28 let max_aniso =
29 unsafe { instance.get_physical_device_properties(physical_device).limits.max_sampler_anisotropy.min(16.0) };
30 let sampler = sampler::create_linear_repeat_aniso_sampler(device, max_aniso)?;
31
32 let desc = DescriptorSetDesc::new()
33 .with_immutable_sampler(0, ShaderStage::Fragment, sampler)
34 .with_bindless_sampled_images(1, ShaderStage::Fragment, MAX_TEXTURES);
35
36 let set_id = descriptors.create_set(desc)?;
37
38 let mut this = Self { set_id, sampler, next_slot: 0, owned_textures: Vec::new(), device: device.clone() };
39
40 let white = GpuTexture::upload(
41 DeviceContext { device, physical_device, instance },
42 SubmitContext { command_pool, queue },
43 TextureSource {
44 pixels: &[255u8, 255, 255, 255],
45 width: 1,
46 height: 1,
47 format: Format::Rgba8Srgb,
48 name: "white_fallback",
49 },
50 )?;
51 let slot = this.alloc_slot(descriptors, white.view);
52 assert_eq!(slot, 0, "white fallback должен быть слотом 0");
53 this.owned_textures.push(white);
54
55 Ok(this)
56 }
57
58 pub fn alloc_slot(&mut self, descriptors: &DescriptorAllocator, view: vk::ImageView) -> u32 {
59 let slot = self.next_slot;
60 assert!(slot < MAX_TEXTURES, "bindless texture array is full");
61 descriptors.write_sampled_image_array(self.set_id, 1, slot, view);
62 self.next_slot += 1;
63 slot
64 }
65
66 pub fn update_slot(&self, descriptors: &DescriptorAllocator, slot: u32, view: vk::ImageView) {
67 assert!(slot < self.next_slot);
68 descriptors.write_sampled_image_array(self.set_id, 1, slot, view);
69 }
70
71 pub fn next_slot(&self) -> u32 {
72 self.next_slot
73 }
74}
75
76impl Drop for BindlessSet {
77 fn drop(&mut self) {
78 unsafe { self.device.destroy_sampler(self.sampler, None) };
79 }
80}