vulkan: add support for blend buffers
This commit is contained in:
parent
1220539a41
commit
cb9da22ec2
20 changed files with 638 additions and 78 deletions
139
src/gfx_apis/vulkan/blend_buffer.rs
Normal file
139
src/gfx_apis/vulkan/blend_buffer.rs
Normal file
|
|
@ -0,0 +1,139 @@
|
|||
use {
|
||||
crate::{
|
||||
gfx_api::GfxBlendBuffer,
|
||||
gfx_apis::vulkan::{
|
||||
VulkanError,
|
||||
format::{BLEND_FORMAT, BLEND_USAGE},
|
||||
image::{QueueFamily, QueueState, VulkanImage, VulkanImageMemory},
|
||||
renderer::VulkanRenderer,
|
||||
},
|
||||
utils::on_drop::OnDrop,
|
||||
},
|
||||
ash::vk::{
|
||||
DescriptorDataEXT, DescriptorGetInfoEXT, DescriptorImageInfo, DescriptorType, Extent3D,
|
||||
ImageAspectFlags, ImageCreateInfo, ImageLayout, ImageSubresourceRange, ImageTiling,
|
||||
ImageType, ImageViewCreateInfo, ImageViewType, SampleCountFlags, SharingMode,
|
||||
},
|
||||
gpu_alloc::UsageFlags,
|
||||
std::{any::Any, cell::Cell, collections::hash_map::Entry, rc::Rc},
|
||||
};
|
||||
|
||||
impl VulkanRenderer {
|
||||
pub fn acquire_blend_buffer(
|
||||
self: &Rc<Self>,
|
||||
width: i32,
|
||||
height: i32,
|
||||
) -> Result<Rc<VulkanImage>, VulkanError> {
|
||||
let Some(db) = &self.device.descriptor_buffer else {
|
||||
return Err(VulkanError::NoDescriptorBuffer);
|
||||
};
|
||||
if width <= 0 || height <= 0 {
|
||||
return Err(VulkanError::NonPositiveImageSize);
|
||||
}
|
||||
let width = width as u32;
|
||||
let height = height as u32;
|
||||
let cached = &mut *self.blend_buffers.borrow_mut();
|
||||
let cached = cached.entry((width, height));
|
||||
if let Entry::Occupied(entry) = &cached {
|
||||
if let Some(buffer) = entry.get().upgrade() {
|
||||
return Ok(buffer);
|
||||
}
|
||||
}
|
||||
let limits = self.device.blend_limits;
|
||||
if width > limits.max_width || height > limits.max_height {
|
||||
return Err(VulkanError::ImageTooLarge);
|
||||
}
|
||||
let create_info = ImageCreateInfo::default()
|
||||
.image_type(ImageType::TYPE_2D)
|
||||
.format(BLEND_FORMAT.vk_format)
|
||||
.mip_levels(1)
|
||||
.array_layers(1)
|
||||
.tiling(ImageTiling::OPTIMAL)
|
||||
.samples(SampleCountFlags::TYPE_1)
|
||||
.sharing_mode(SharingMode::EXCLUSIVE)
|
||||
.initial_layout(ImageLayout::UNDEFINED)
|
||||
.extent(Extent3D {
|
||||
width,
|
||||
height,
|
||||
depth: 1,
|
||||
})
|
||||
.usage(BLEND_USAGE);
|
||||
let image = unsafe { self.device.device.create_image(&create_info, None) };
|
||||
let image = image.map_err(VulkanError::CreateImage)?;
|
||||
let destroy_image = OnDrop(|| unsafe { self.device.device.destroy_image(image, None) });
|
||||
let memory_requirements =
|
||||
unsafe { self.device.device.get_image_memory_requirements(image) };
|
||||
let allocation =
|
||||
self.allocator
|
||||
.alloc(&memory_requirements, UsageFlags::FAST_DEVICE_ACCESS, false)?;
|
||||
let res = unsafe {
|
||||
self.device
|
||||
.device
|
||||
.bind_image_memory(image, allocation.memory, allocation.offset)
|
||||
};
|
||||
res.map_err(VulkanError::BindImageMemory)?;
|
||||
let image_view_create_info = ImageViewCreateInfo::default()
|
||||
.image(image)
|
||||
.format(BLEND_FORMAT.vk_format)
|
||||
.view_type(ImageViewType::TYPE_2D)
|
||||
.subresource_range(ImageSubresourceRange {
|
||||
aspect_mask: ImageAspectFlags::COLOR,
|
||||
base_mip_level: 0,
|
||||
level_count: 1,
|
||||
base_array_layer: 0,
|
||||
layer_count: 1,
|
||||
});
|
||||
let view = unsafe {
|
||||
self.device
|
||||
.device
|
||||
.create_image_view(&image_view_create_info, None)
|
||||
};
|
||||
let view = view.map_err(VulkanError::CreateImageView)?;
|
||||
destroy_image.forget();
|
||||
let sampled_image_descriptor = {
|
||||
let mut buf = vec![0; self.device.sampled_image_descriptor_size].into_boxed_slice();
|
||||
let image_info = DescriptorImageInfo::default()
|
||||
.image_view(view)
|
||||
.image_layout(ImageLayout::SHADER_READ_ONLY_OPTIMAL);
|
||||
let info = DescriptorGetInfoEXT::default()
|
||||
.ty(DescriptorType::SAMPLED_IMAGE)
|
||||
.data(DescriptorDataEXT {
|
||||
p_sampled_image: &image_info,
|
||||
});
|
||||
unsafe {
|
||||
db.get_descriptor(&info, &mut buf);
|
||||
}
|
||||
buf
|
||||
};
|
||||
let img = Rc::new(VulkanImage {
|
||||
renderer: self.clone(),
|
||||
format: BLEND_FORMAT,
|
||||
width,
|
||||
height,
|
||||
stride: 0,
|
||||
texture_view: view,
|
||||
render_view: None,
|
||||
image,
|
||||
is_undefined: Cell::new(true),
|
||||
contents_are_undefined: Cell::new(true),
|
||||
queue_state: Cell::new(QueueState::Acquired {
|
||||
family: QueueFamily::Gfx,
|
||||
}),
|
||||
ty: VulkanImageMemory::Blend(allocation),
|
||||
bridge: None,
|
||||
shader_read_only_optimal_descriptor: Box::new([]),
|
||||
sampled_image_descriptor,
|
||||
descriptor_buffer_version: Default::default(),
|
||||
descriptor_buffer_offset: Default::default(),
|
||||
execution_version: Default::default(),
|
||||
});
|
||||
cached.insert_entry(Rc::downgrade(&img));
|
||||
Ok(img)
|
||||
}
|
||||
}
|
||||
|
||||
impl GfxBlendBuffer for VulkanImage {
|
||||
fn into_any(self: Rc<Self>) -> Rc<dyn Any> {
|
||||
self
|
||||
}
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue