use super::*;
use crate::vulkan::{RafxDeviceContextVulkan, RafxRenderpassVulkan};
use crate::*;
use fnv::FnvHasher;
use std::hash::{Hash, Hasher};
pub(crate) struct RafxFramebufferVulkanCache {
cache: LruCache<RafxFramebufferVulkan>,
}
impl RafxFramebufferVulkanCache {
pub(crate) fn new(max_count: usize) -> Self {
RafxFramebufferVulkanCache {
cache: LruCache::new(max_count),
}
}
pub(crate) fn clear(&mut self) {
self.cache.clear();
}
pub(crate) fn framebuffer_hash(
color_targets: &[RafxColorRenderTargetBinding],
depth_target: Option<&RafxDepthStencilRenderTargetBinding>,
) -> u64 {
let mut hasher = FnvHasher::default();
for color_target in color_targets {
color_target
.texture
.vk_texture()
.unwrap()
.texture_id()
.hash(&mut hasher);
color_target.mip_slice.hash(&mut hasher);
color_target.array_slice.hash(&mut hasher);
if let Some(resolve_target) = color_target.resolve_target {
resolve_target
.vk_texture()
.unwrap()
.texture_id()
.hash(&mut hasher);
color_target.resolve_mip_slice.hash(&mut hasher);
color_target.resolve_array_slice.hash(&mut hasher);
}
}
if let Some(depth_target) = &depth_target {
depth_target
.texture
.vk_texture()
.unwrap()
.texture_id()
.hash(&mut hasher);
depth_target.mip_slice.hash(&mut hasher);
depth_target.array_slice.hash(&mut hasher);
}
hasher.finish()
}
pub(crate) fn create_framebuffer(
device_context: &RafxDeviceContextVulkan,
renderpass: &RafxRenderpassVulkan,
color_targets: &[RafxColorRenderTargetBinding],
depth_target: Option<&RafxDepthStencilRenderTargetBinding>,
) -> RafxResult<RafxFramebufferVulkan> {
let mut color_attachments = Vec::with_capacity(color_targets.len());
let mut resolve_attachments = Vec::with_capacity(color_targets.len());
for color_target in color_targets {
color_attachments.push(RafxFramebufferVulkanAttachment {
texture: color_target.texture.vk_texture().unwrap().clone(),
array_slice: color_target.array_slice,
mip_slice: color_target.mip_slice,
});
if let Some(resolve_target) = color_target.resolve_target {
resolve_attachments.push(RafxFramebufferVulkanAttachment {
texture: resolve_target.vk_texture().unwrap().clone(),
array_slice: color_target.resolve_array_slice,
mip_slice: color_target.resolve_mip_slice,
})
}
}
RafxFramebufferVulkan::new(
device_context,
&RafxFramebufferVulkanDef {
renderpass: renderpass.clone(),
color_attachments,
resolve_attachments,
depth_stencil_attachment: depth_target.as_ref().map(|x| {
RafxFramebufferVulkanAttachment {
texture: x.texture.vk_texture().unwrap().clone(),
array_slice: x.array_slice,
mip_slice: x.mip_slice,
}
}),
},
)
}
pub(crate) fn get_or_create_framebuffer(
&mut self,
device_context: &RafxDeviceContextVulkan,
renderpass: &RafxRenderpassVulkan,
color_targets: &[RafxColorRenderTargetBinding],
depth_target: Option<&RafxDepthStencilRenderTargetBinding>,
) -> RafxResult<RafxFramebufferVulkan> {
let hash = Self::framebuffer_hash(color_targets, depth_target);
self.cache.get_or_create(hash, || {
Self::create_framebuffer(device_context, renderpass, color_targets, depth_target)
})
}
}