Skip to main content

ursus_core/assets/storage/
texture.rs

1use crate::assets::registry::TextureHandle;
2use crate::render::gfx::descriptor::DescriptorAllocator;
3use crate::vulkan::core::{DeviceContext, SubmitContext};
4use crate::vulkan::resources::texture::TextureSource;
5use crate::vulkan::{BindlessSet, GpuTexture};
6use ash::vk;
7use std::collections::HashMap;
8
9pub const BINDLESS_SLOT_WHITE: u32 = 0;
10
11/// Owns loaded GPU textures and their bindless slots.
12/// TextureHandle (stable, assigned by AssetRegistry on the CPU side) -> bindless slot -> GpuTexture.
13pub struct GpuTextureStore {
14    slots: HashMap<TextureHandle, u32>,
15    textures: HashMap<u32, GpuTexture>,
16    bindless: BindlessSet,
17    device: ash::Device,
18    physical_device: vk::PhysicalDevice,
19    instance: ash::Instance,
20    command_pool: vk::CommandPool,
21    queue: vk::Queue,
22}
23
24impl GpuTextureStore {
25    pub fn new(
26        device: ash::Device,
27        physical_device: vk::PhysicalDevice,
28        instance: ash::Instance,
29        command_pool: vk::CommandPool,
30        descriptors: &mut DescriptorAllocator,
31        queue: vk::Queue,
32    ) -> anyhow::Result<Self> {
33        let bindless = BindlessSet::new(&device, physical_device, &instance, descriptors, command_pool, queue)?;
34        assert_eq!(bindless.next_slot(), 1, "slot 0 must be white fallback");
35
36        Ok(Self {
37            slots: HashMap::new(),
38            textures: HashMap::new(),
39            bindless,
40            device,
41            physical_device,
42            instance,
43            command_pool,
44            queue,
45        })
46    }
47
48    pub fn upload(
49        &mut self,
50        descriptors: &DescriptorAllocator,
51        handle: TextureHandle,
52        upload: TextureSource,
53    ) -> anyhow::Result<()> {
54        let tex = GpuTexture::upload(
55            DeviceContext { device: &self.device, physical_device: self.physical_device, instance: &self.instance },
56            SubmitContext { command_pool: self.command_pool, queue: self.queue },
57            upload,
58        )?;
59        let slot = self.bindless.alloc_slot(descriptors, tex.view);
60        self.slots.insert(handle, slot);
61        self.textures.insert(slot, tex);
62        Ok(())
63    }
64
65    pub fn slot(&self, handle: TextureHandle) -> u32 {
66        self.slots.get(&handle).copied().unwrap_or(BINDLESS_SLOT_WHITE)
67    }
68
69    pub fn bindless(&self) -> &BindlessSet {
70        &self.bindless
71    }
72
73    pub fn bindless_mut(&mut self) -> &mut BindlessSet {
74        &mut self.bindless
75    }
76}