librashader/librashader-runtime-vk/src/luts.rs

234 lines
7.9 KiB
Rust
Raw Normal View History

2023-01-14 09:59:22 +11:00
use crate::filter_chain::VulkanObjects;
use crate::memory::{VulkanBuffer, VulkanImageMemory};
2023-01-12 15:05:08 +11:00
use crate::texture::{InputImage, VulkanImage};
2022-12-22 13:39:31 +11:00
use crate::{error, util};
2022-12-22 13:13:35 +11:00
use ash::vk;
use librashader_presets::TextureConfig;
2022-12-22 13:39:31 +11:00
use librashader_runtime::image::{Image, BGRA8};
2022-12-22 13:13:35 +11:00
use librashader_runtime::scaling::MipmapSize;
2023-01-15 07:10:40 +11:00
pub(crate) struct LutTexture {
_memory: VulkanImageMemory,
_staging: VulkanBuffer,
2023-01-12 15:05:08 +11:00
pub image: InputImage,
2022-12-22 13:13:35 +11:00
}
impl LutTexture {
2022-12-22 13:39:31 +11:00
pub fn new(
2023-01-14 09:59:22 +11:00
vulkan: &VulkanObjects,
cmd: vk::CommandBuffer,
2022-12-22 13:39:31 +11:00
image: Image<BGRA8>,
config: &TextureConfig,
) -> error::Result<LutTexture> {
2024-08-01 15:23:18 +10:00
let image_info = vk::ImageCreateInfo::default()
2022-12-22 13:13:35 +11:00
.image_type(vk::ImageType::TYPE_2D)
.format(vk::Format::B8G8R8A8_UNORM)
.extent(image.size.into())
.mip_levels(if config.mipmap {
image.size.calculate_miplevels()
} else {
1
})
.array_layers(1)
.samples(vk::SampleCountFlags::TYPE_1)
.tiling(vk::ImageTiling::OPTIMAL)
2022-12-22 13:39:31 +11:00
.usage(
vk::ImageUsageFlags::SAMPLED
| vk::ImageUsageFlags::TRANSFER_SRC
| vk::ImageUsageFlags::TRANSFER_DST,
)
.initial_layout(vk::ImageLayout::UNDEFINED);
2022-12-22 13:13:35 +11:00
2022-12-22 13:39:31 +11:00
let texture = unsafe { vulkan.device.create_image(&image_info, None)? };
2022-12-22 13:13:35 +11:00
let memory = unsafe {
2023-01-16 03:08:13 +11:00
let mem_reqs = vulkan.device.get_image_memory_requirements(texture);
VulkanImageMemory::new(&vulkan.device, &vulkan.alloc, mem_reqs, &texture)?
2022-12-22 13:13:35 +11:00
};
2024-08-01 15:23:18 +10:00
let image_subresource = vk::ImageSubresourceRange::default()
2022-12-22 13:13:35 +11:00
.level_count(image_info.mip_levels)
.layer_count(1)
.aspect_mask(vk::ImageAspectFlags::COLOR);
2022-12-22 13:13:35 +11:00
2024-08-01 15:23:18 +10:00
let swizzle_components = vk::ComponentMapping::default()
2022-12-22 13:13:35 +11:00
.r(vk::ComponentSwizzle::R)
.g(vk::ComponentSwizzle::G)
.b(vk::ComponentSwizzle::B)
.a(vk::ComponentSwizzle::A);
2022-12-22 13:13:35 +11:00
2024-08-01 15:23:18 +10:00
let view_info = vk::ImageViewCreateInfo::default()
2022-12-22 13:13:35 +11:00
.view_type(vk::ImageViewType::TYPE_2D)
.format(vk::Format::B8G8R8A8_UNORM)
2023-01-16 03:08:13 +11:00
.image(texture)
2024-08-01 15:23:18 +10:00
.subresource_range(image_subresource)
.components(swizzle_components);
2022-12-22 13:13:35 +11:00
2022-12-22 13:39:31 +11:00
let texture_view = unsafe { vulkan.device.create_image_view(&view_info, None)? };
2022-12-22 13:13:35 +11:00
2022-12-22 13:39:31 +11:00
let mut staging = VulkanBuffer::new(
&vulkan.device,
&vulkan.alloc,
2022-12-22 13:39:31 +11:00
vk::BufferUsageFlags::TRANSFER_SRC,
image.bytes.len(),
)?;
staging.as_mut_slice()?.copy_from_slice(&image.bytes);
2022-12-22 13:13:35 +11:00
unsafe {
2022-12-22 13:39:31 +11:00
util::vulkan_image_layout_transition_levels(
&vulkan.device,
cmd,
2022-12-22 13:39:31 +11:00
texture,
vk::REMAINING_MIP_LEVELS,
vk::ImageLayout::UNDEFINED,
2022-12-22 13:13:35 +11:00
if config.mipmap {
vk::ImageLayout::GENERAL
} else {
vk::ImageLayout::TRANSFER_DST_OPTIMAL
},
vk::AccessFlags::empty(),
vk::AccessFlags::TRANSFER_WRITE,
vk::PipelineStageFlags::TOP_OF_PIPE,
vk::PipelineStageFlags::TRANSFER,
2022-12-22 13:39:31 +11:00
vk::QUEUE_FAMILY_IGNORED,
vk::QUEUE_FAMILY_IGNORED,
2022-12-22 13:13:35 +11:00
);
2024-08-01 15:23:18 +10:00
let builder = vk::BufferImageCopy::default()
.image_subresource(
2024-08-01 15:23:18 +10:00
vk::ImageSubresourceLayers::default()
.aspect_mask(vk::ImageAspectFlags::COLOR)
.mip_level(0)
.base_array_layer(0)
.layer_count(1),
)
.image_extent(image.size.into());
2022-12-22 13:39:31 +11:00
vulkan.device.cmd_copy_buffer_to_image(
cmd,
2022-12-22 13:39:31 +11:00
staging.handle,
texture,
if config.mipmap {
vk::ImageLayout::GENERAL
} else {
vk::ImageLayout::TRANSFER_DST_OPTIMAL
},
2024-08-01 15:23:18 +10:00
&[builder],
2022-12-22 13:39:31 +11:00
)
2022-12-22 13:13:35 +11:00
}
// generate mipmaps
for level in 1..image_info.mip_levels {
let source_size = image.size.scale_mipmap(level - 1);
let target_size = image.size.scale_mipmap(level);
let src_offsets = [
2022-12-22 13:39:31 +11:00
vk::Offset3D { x: 0, y: 0, z: 0 },
2022-12-22 13:13:35 +11:00
vk::Offset3D {
x: source_size.width as i32,
y: source_size.height as i32,
z: 1,
},
];
let dst_offsets = [
2022-12-22 13:39:31 +11:00
vk::Offset3D { x: 0, y: 0, z: 0 },
2022-12-22 13:13:35 +11:00
vk::Offset3D {
x: target_size.width as i32,
y: target_size.height as i32,
z: 1,
},
];
2024-08-01 15:23:18 +10:00
let src_subresource = vk::ImageSubresourceLayers::default()
2022-12-22 13:13:35 +11:00
.aspect_mask(vk::ImageAspectFlags::COLOR)
.mip_level(level - 1)
.base_array_layer(0)
.layer_count(1);
2022-12-22 13:13:35 +11:00
2024-08-01 15:23:18 +10:00
let dst_subresource = vk::ImageSubresourceLayers::default()
2022-12-22 13:13:35 +11:00
.aspect_mask(vk::ImageAspectFlags::COLOR)
.mip_level(level)
.base_array_layer(0)
.layer_count(1);
2022-12-22 13:13:35 +11:00
2024-08-01 15:23:18 +10:00
let image_blit = vk::ImageBlit::default()
.src_subresource(src_subresource)
2022-12-22 13:13:35 +11:00
.src_offsets(src_offsets)
2024-08-01 15:23:18 +10:00
.dst_subresource(dst_subresource)
.dst_offsets(dst_offsets);
2022-12-22 13:13:35 +11:00
unsafe {
2022-12-22 13:39:31 +11:00
util::vulkan_image_layout_transition_levels(
&vulkan.device,
cmd,
2022-12-22 13:39:31 +11:00
texture,
vk::REMAINING_MIP_LEVELS,
vk::ImageLayout::GENERAL,
vk::ImageLayout::GENERAL,
vk::AccessFlags::TRANSFER_WRITE,
vk::AccessFlags::TRANSFER_READ,
vk::PipelineStageFlags::TRANSFER,
vk::PipelineStageFlags::TRANSFER,
vk::QUEUE_FAMILY_IGNORED,
vk::QUEUE_FAMILY_IGNORED,
2022-12-22 13:13:35 +11:00
);
// todo: respect mipmap filter?
2022-12-22 13:39:31 +11:00
vulkan.device.cmd_blit_image(
cmd,
2022-12-22 13:39:31 +11:00
texture,
vk::ImageLayout::GENERAL,
texture,
vk::ImageLayout::GENERAL,
2024-08-01 15:23:18 +10:00
&[image_blit],
config.filter_mode.into(),
2022-12-22 13:39:31 +11:00
);
2022-12-22 13:13:35 +11:00
}
}
unsafe {
2022-12-22 13:39:31 +11:00
util::vulkan_image_layout_transition_levels(
&vulkan.device,
cmd,
2022-12-22 13:39:31 +11:00
texture,
vk::REMAINING_MIP_LEVELS,
if config.mipmap {
vk::ImageLayout::GENERAL
} else {
vk::ImageLayout::TRANSFER_DST_OPTIMAL
},
vk::ImageLayout::SHADER_READ_ONLY_OPTIMAL,
vk::AccessFlags::TRANSFER_WRITE,
2022-12-22 14:02:57 +11:00
vk::AccessFlags::SHADER_READ,
2022-12-22 13:39:31 +11:00
vk::PipelineStageFlags::TRANSFER,
vk::PipelineStageFlags::FRAGMENT_SHADER,
vk::QUEUE_FAMILY_IGNORED,
vk::QUEUE_FAMILY_IGNORED,
2022-12-22 13:13:35 +11:00
);
}
Ok(LutTexture {
_memory: memory,
_staging: staging,
2023-01-12 15:05:08 +11:00
image: InputImage {
2022-12-22 17:30:14 +11:00
image_view: texture_view,
2022-12-29 16:50:48 +11:00
image: VulkanImage {
size: image.size,
image: texture,
2023-01-10 14:54:54 +11:00
format: vk::Format::B8G8R8A8_UNORM,
2022-12-29 16:50:48 +11:00
},
2022-12-22 17:30:14 +11:00
filter_mode: config.filter_mode,
wrap_mode: config.wrap_mode,
mip_filter: config.filter_mode,
2023-01-10 14:54:54 +11:00
},
2022-12-22 13:13:35 +11:00
})
}
2022-12-22 13:39:31 +11:00
}
2023-01-15 19:01:23 +11:00
impl AsRef<InputImage> for LutTexture {
fn as_ref(&self) -> &InputImage {
&self.image
}
2023-01-15 19:06:09 +11:00
}