sim2d/streaming_renderer/texture/
atlas.rs1use {
2 super::Texture,
3 anyhow::{Context, Result},
4 ash::vk,
5 demo_vk::graphics::vulkan::{VulkanContext, raii},
6 std::sync::Arc,
7};
8
9const MAX_TEXTURES: u32 = 10_000;
13
14pub struct TextureAtlas {
31 textures: Vec<Arc<Texture>>,
33
34 _sampler: raii::Sampler,
36
37 descriptor_set_layout: raii::DescriptorSetLayout,
38 descriptor_set: vk::DescriptorSet,
39 _descriptor_pool: raii::DescriptorPool,
40}
41
42impl TextureAtlas {
43 pub fn new(ctx: &VulkanContext) -> Result<Self> {
44 let sampler = raii::Sampler::new(
45 "TextureAtlas Immutable Sampler",
46 ctx.device.clone(),
47 &vk::SamplerCreateInfo {
48 mag_filter: vk::Filter::LINEAR,
49 min_filter: vk::Filter::LINEAR,
50 mipmap_mode: vk::SamplerMipmapMode::LINEAR,
51 address_mode_u: vk::SamplerAddressMode::CLAMP_TO_EDGE,
52 address_mode_v: vk::SamplerAddressMode::CLAMP_TO_EDGE,
53 address_mode_w: vk::SamplerAddressMode::CLAMP_TO_EDGE,
54 mip_lod_bias: 0.0,
55 anisotropy_enable: vk::FALSE,
56 max_anisotropy: 0.0,
57 compare_enable: vk::FALSE,
58 compare_op: vk::CompareOp::ALWAYS,
59 min_lod: 0.0,
60 max_lod: vk::LOD_CLAMP_NONE,
61 border_color: vk::BorderColor::FLOAT_OPAQUE_WHITE,
62 unnormalized_coordinates: vk::FALSE,
63 ..Default::default()
64 },
65 )
66 .context("Unable to create texture atlas sampler!")?;
67
68 let descriptor_set_layout = {
69 let bindings = [
70 vk::DescriptorSetLayoutBinding {
71 binding: 0,
72 descriptor_type: vk::DescriptorType::SAMPLER,
73 descriptor_count: 1,
74 stage_flags: vk::ShaderStageFlags::FRAGMENT,
75 p_immutable_samplers: &sampler.raw,
76 ..Default::default()
77 },
78 vk::DescriptorSetLayoutBinding {
79 binding: 1,
80 descriptor_type: vk::DescriptorType::SAMPLED_IMAGE,
81 descriptor_count: MAX_TEXTURES,
82 stage_flags: vk::ShaderStageFlags::FRAGMENT,
83 p_immutable_samplers: std::ptr::null(),
84 _marker: std::marker::PhantomData,
85 },
86 ];
87 let binding_flags = [
88 vk::DescriptorBindingFlags::empty(),
89 vk::DescriptorBindingFlags::PARTIALLY_BOUND
90 | vk::DescriptorBindingFlags::VARIABLE_DESCRIPTOR_COUNT
91 | vk::DescriptorBindingFlags::UPDATE_AFTER_BIND
92 | vk::DescriptorBindingFlags::UPDATE_UNUSED_WHILE_PENDING,
93 ];
94 let mut binding_flags_create_info =
95 vk::DescriptorSetLayoutBindingFlagsCreateInfo {
96 binding_count: binding_flags.len() as u32,
97 p_binding_flags: binding_flags.as_ptr(),
98 ..Default::default()
99 };
100 let create_info = vk::DescriptorSetLayoutCreateInfo {
101 flags:
102 vk::DescriptorSetLayoutCreateFlags::UPDATE_AFTER_BIND_POOL,
103 binding_count: bindings.len() as u32,
104 p_bindings: bindings.as_ptr(),
105 ..Default::default()
106 }
107 .push_next(&mut binding_flags_create_info);
108 raii::DescriptorSetLayout::new(
109 "TextureAtlas Descriptor Set layout",
110 ctx.device.clone(),
111 &create_info,
112 )
113 .context("Unable to create TextureAtlas descriptor set layout!")?
114 };
115 let descriptor_pool = {
116 let pool_sizes = [
117 vk::DescriptorPoolSize {
118 ty: vk::DescriptorType::SAMPLER,
119 descriptor_count: 1,
120 },
121 vk::DescriptorPoolSize {
122 ty: vk::DescriptorType::SAMPLED_IMAGE,
123 descriptor_count: MAX_TEXTURES,
124 },
125 ];
126 raii::DescriptorPool::new(
127 "TextureAtlas DescriptorPool",
128 ctx.device.clone(),
129 &vk::DescriptorPoolCreateInfo {
130 flags: vk::DescriptorPoolCreateFlags::UPDATE_AFTER_BIND,
131 max_sets: 1,
132 pool_size_count: pool_sizes.len() as u32,
133 p_pool_sizes: pool_sizes.as_ptr(),
134 ..Default::default()
135 },
136 )
137 .context("Error creating TextureAtlas descriptor pool!")?
138 };
139 let descriptor_set = {
140 let counts = [MAX_TEXTURES];
141 let mut descriptor_set_variable_descriptor_count_allocate_info =
142 vk::DescriptorSetVariableDescriptorCountAllocateInfo {
143 descriptor_set_count: 1,
144 p_descriptor_counts: counts.as_ptr(),
145 ..Default::default()
146 };
147 let allocate_info = vk::DescriptorSetAllocateInfo {
148 descriptor_pool: descriptor_pool.raw,
149 descriptor_set_count: 1,
150 p_set_layouts: &descriptor_set_layout.raw,
151 ..Default::default()
152 }
153 .push_next(
154 &mut descriptor_set_variable_descriptor_count_allocate_info,
155 );
156 unsafe {
157 ctx.allocate_descriptor_sets(&allocate_info).context(
158 "Unable to allocate TextureAtlas descriptor set!",
159 )?[0]
160 }
161 };
162
163 Ok(Self {
164 textures: vec![],
165 _sampler: sampler,
166 descriptor_set_layout,
167 _descriptor_pool: descriptor_pool,
168 descriptor_set,
169 })
170 }
171
172 pub fn descriptor_set_layout(&self) -> &raii::DescriptorSetLayout {
173 &self.descriptor_set_layout
174 }
175
176 pub fn descriptor_set(&self) -> vk::DescriptorSet {
180 self.descriptor_set
181 }
182
183 pub fn add_texture(
186 &mut self,
187 ctx: &VulkanContext,
188 texture: Arc<Texture>,
189 ) -> i32 {
190 let texture_index = self.textures.len() as i32;
191 let view = texture.view().raw;
192 self.textures.push(texture);
193
194 unsafe {
197 let image_info = vk::DescriptorImageInfo {
198 sampler: vk::Sampler::null(),
199 image_view: view,
200 image_layout: vk::ImageLayout::SHADER_READ_ONLY_OPTIMAL,
201 };
202 ctx.update_descriptor_sets(
203 &[vk::WriteDescriptorSet {
204 dst_set: self.descriptor_set,
205 dst_binding: 1,
206 dst_array_element: texture_index as u32,
207 descriptor_count: 1,
208 descriptor_type: vk::DescriptorType::SAMPLED_IMAGE,
209 p_image_info: &image_info,
210 p_buffer_info: std::ptr::null(),
211 p_texel_buffer_view: std::ptr::null(),
212 ..Default::default()
213 }],
214 &[],
215 );
216 }
217
218 texture_index
219 }
220}