2023-01-14 09:59:22 +11:00
|
|
|
use crate::filter_chain::VulkanObjects;
|
2023-02-10 10:11:34 +11:00
|
|
|
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 {
|
2023-02-11 18:42:33 +11:00
|
|
|
_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,
|
2023-01-13 17:19:41 +11:00
|
|
|
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,
|
|
|
|
)
|
2023-02-17 09:33:47 +11:00
|
|
|
.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);
|
2023-02-10 10:11:34 +11:00
|
|
|
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)
|
2023-02-17 09:33:47 +11:00
|
|
|
.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)
|
2023-02-17 09:33:47 +11:00
|
|
|
.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,
|
2023-02-10 10:11:34 +11:00
|
|
|
&vulkan.alloc,
|
2022-12-22 13:39:31 +11:00
|
|
|
vk::BufferUsageFlags::TRANSFER_SRC,
|
|
|
|
image.bytes.len(),
|
|
|
|
)?;
|
2023-02-10 10:11:34 +11:00
|
|
|
|
|
|
|
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,
|
2023-01-13 17:19:41 +11:00
|
|
|
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()
|
2023-02-16 14:57:20 +11:00
|
|
|
.image_subresource(
|
2024-08-01 15:23:18 +10:00
|
|
|
vk::ImageSubresourceLayers::default()
|
2023-02-16 14:57:20 +11:00
|
|
|
.aspect_mask(vk::ImageAspectFlags::COLOR)
|
|
|
|
.mip_level(0)
|
|
|
|
.base_array_layer(0)
|
2023-02-17 09:33:47 +11:00
|
|
|
.layer_count(1),
|
2023-02-16 14:57:20 +11:00
|
|
|
)
|
|
|
|
.image_extent(image.size.into());
|
|
|
|
|
2022-12-22 13:39:31 +11:00
|
|
|
vulkan.device.cmd_copy_buffer_to_image(
|
2023-01-13 17:19:41 +11:00
|
|
|
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)
|
2023-02-17 09:33:47 +11:00
|
|
|
.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)
|
2023-02-17 09:33:47 +11:00
|
|
|
.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)
|
2023-02-17 09:33:47 +11:00
|
|
|
.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,
|
2023-01-13 17:19:41 +11:00
|
|
|
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(
|
2023-01-13 17:19:41 +11:00
|
|
|
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],
|
2023-01-13 17:19:41 +11:00
|
|
|
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,
|
2023-01-13 17:19:41 +11:00
|
|
|
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 {
|
2023-02-11 18:42:33 +11:00
|
|
|
_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
|
|
|
}
|