use crate::{RendererError, RendererResult, UniformBuffer};
use std::collections::HashMap;
use wgpu::*;
pub struct RenderResources {
pub sampler: Option<Sampler>,
pub uniform_buffer: Option<UniformBuffer>,
pub image_bind_groups: HashMap<u64, BindGroup>,
pub image_bind_group_layout: Option<BindGroupLayout>,
}
impl RenderResources {
pub fn new() -> Self {
Self {
sampler: None,
uniform_buffer: None,
image_bind_groups: HashMap::new(),
image_bind_group_layout: None,
}
}
pub fn initialize(&mut self, device: &Device) -> RendererResult<()> {
#[cfg(feature = "wgpu-27")]
fn linear_mipmap_filter() -> FilterMode {
FilterMode::Linear
}
#[cfg(any(feature = "wgpu-28", feature = "wgpu-29"))]
fn linear_mipmap_filter() -> MipmapFilterMode {
MipmapFilterMode::Linear
}
let sampler = device.create_sampler(&SamplerDescriptor {
label: Some("Dear ImGui Texture Sampler"),
address_mode_u: AddressMode::ClampToEdge, address_mode_v: AddressMode::ClampToEdge, address_mode_w: AddressMode::ClampToEdge, mag_filter: FilterMode::Linear, min_filter: FilterMode::Linear, mipmap_filter: linear_mipmap_filter(), anisotropy_clamp: 1, ..Default::default()
});
let uniform_buffer = UniformBuffer::new(device, &sampler);
let image_bind_group_layout = device.create_bind_group_layout(&BindGroupLayoutDescriptor {
label: Some("Dear ImGui Image Bind Group Layout"),
entries: &[BindGroupLayoutEntry {
binding: 0,
visibility: ShaderStages::FRAGMENT,
ty: BindingType::Texture {
multisampled: false,
sample_type: TextureSampleType::Float { filterable: true },
view_dimension: TextureViewDimension::D2,
},
count: None,
}],
});
self.sampler = Some(sampler);
self.uniform_buffer = Some(uniform_buffer);
self.image_bind_group_layout = Some(image_bind_group_layout);
Ok(())
}
pub fn create_image_bind_group(
&self,
device: &Device,
texture_view: &TextureView,
) -> RendererResult<BindGroup> {
let layout = self.image_bind_group_layout.as_ref().ok_or_else(|| {
RendererError::InvalidRenderState("Image bind group layout not initialized".to_string())
})?;
let bind_group = device.create_bind_group(&BindGroupDescriptor {
label: Some("Dear ImGui Image Bind Group"),
layout,
entries: &[BindGroupEntry {
binding: 0,
resource: BindingResource::TextureView(texture_view),
}],
});
Ok(bind_group)
}
pub fn get_or_create_image_bind_group(
&mut self,
device: &Device,
texture_id: u64,
texture_view: &TextureView,
) -> RendererResult<&BindGroup> {
if !self.image_bind_groups.contains_key(&texture_id) {
let bind_group = self.create_image_bind_group(device, texture_view)?;
self.image_bind_groups.insert(texture_id, bind_group);
}
self.image_bind_groups.get(&texture_id).ok_or_else(|| {
RendererError::InvalidRenderState("Image bind group missing after creation".to_string())
})
}
pub fn remove_image_bind_group(&mut self, texture_id: u64) {
self.image_bind_groups.remove(&texture_id);
}
pub fn clear_image_bind_groups(&mut self) {
self.image_bind_groups.clear();
}
pub fn sampler(&self) -> Option<&Sampler> {
self.sampler.as_ref()
}
pub fn uniform_buffer(&self) -> Option<&UniformBuffer> {
self.uniform_buffer.as_ref()
}
pub fn common_bind_group(&self) -> Option<&BindGroup> {
self.uniform_buffer.as_ref().map(|ub| ub.bind_group())
}
pub fn image_bind_group_layout(&self) -> Option<&BindGroupLayout> {
self.image_bind_group_layout.as_ref()
}
pub fn is_initialized(&self) -> bool {
self.sampler.is_some()
&& self.uniform_buffer.is_some()
&& self.image_bind_group_layout.is_some()
}
pub fn stats(&self) -> RenderResourcesStats {
RenderResourcesStats {
image_bind_groups_count: self.image_bind_groups.len(),
is_initialized: self.is_initialized(),
}
}
}
impl Default for RenderResources {
fn default() -> Self {
Self::new()
}
}
#[derive(Debug, Clone)]
pub struct RenderResourcesStats {
pub image_bind_groups_count: usize,
pub is_initialized: bool,
}