1use crate::filter_chain::VulkanObjects;
2use crate::memory::VulkanImageMemory;
3use crate::{error, util};
4use ash::vk;
5use gpu_allocator::vulkan::Allocator;
6use parking_lot::Mutex;
7use std::sync::Arc;
8
9use crate::error::FilterChainError;
10use librashader_common::{FilterMode, GetSize, ImageFormat, Size, WrapMode};
11use librashader_presets::Scale2D;
12use librashader_runtime::scaling::{MipmapSize, ScaleFramebuffer, ViewportSize};
13
14pub struct OwnedImage {
15 pub device: Arc<ash::Device>,
16 pub allocator: Arc<Mutex<Allocator>>,
17 pub image_view: vk::ImageView,
18 pub image: VulkanImage,
19 pub max_miplevels: u32,
20 pub levels: u32,
21 pub _memory: VulkanImageMemory,
22}
23
24#[derive(Clone)]
25pub struct OwnedImageLayout {
26 pub(crate) dst_layout: vk::ImageLayout,
27 pub(crate) dst_access: vk::AccessFlags,
28 pub(crate) src_stage: vk::PipelineStageFlags,
29 pub(crate) dst_stage: vk::PipelineStageFlags,
30 pub(crate) cmd: vk::CommandBuffer,
31}
32
33impl OwnedImage {
34 fn new_internal(
35 device: Arc<ash::Device>,
36 alloc: &Arc<Mutex<Allocator>>,
37 size: Size<u32>,
38 mut format: ImageFormat,
39 max_miplevels: u32,
40 ) -> error::Result<OwnedImage> {
41 if format == ImageFormat::Unknown {
43 format = ImageFormat::R8G8B8A8Unorm
44 }
45 let image_create_info = vk::ImageCreateInfo::default()
46 .image_type(vk::ImageType::TYPE_2D)
47 .format(format.into())
48 .extent(size.into())
49 .mip_levels(std::cmp::min(max_miplevels, size.calculate_miplevels()))
50 .array_layers(1)
51 .samples(vk::SampleCountFlags::TYPE_1)
52 .tiling(vk::ImageTiling::OPTIMAL)
53 .flags(vk::ImageCreateFlags::MUTABLE_FORMAT)
54 .usage(
55 vk::ImageUsageFlags::SAMPLED
56 | vk::ImageUsageFlags::COLOR_ATTACHMENT
57 | vk::ImageUsageFlags::TRANSFER_DST
58 | vk::ImageUsageFlags::TRANSFER_SRC,
59 )
60 .sharing_mode(vk::SharingMode::EXCLUSIVE)
61 .initial_layout(vk::ImageLayout::UNDEFINED);
62
63 let image = unsafe { device.create_image(&image_create_info, None)? };
64 let mem_reqs = unsafe { device.get_image_memory_requirements(image) };
65
66 let memory = VulkanImageMemory::new(&device, alloc, mem_reqs, &image)?;
67 let image_subresource = vk::ImageSubresourceRange::default()
68 .base_mip_level(0)
69 .base_array_layer(0)
70 .level_count(image_create_info.mip_levels)
71 .layer_count(1)
72 .aspect_mask(vk::ImageAspectFlags::COLOR);
73
74 let swizzle_components = vk::ComponentMapping::default()
75 .r(vk::ComponentSwizzle::R)
76 .g(vk::ComponentSwizzle::G)
77 .b(vk::ComponentSwizzle::B)
78 .a(vk::ComponentSwizzle::A);
79
80 let view_info = vk::ImageViewCreateInfo::default()
81 .view_type(vk::ImageViewType::TYPE_2D)
82 .format(format.into())
83 .image(image)
84 .subresource_range(image_subresource)
85 .components(swizzle_components);
86
87 let image_view = unsafe { device.create_image_view(&view_info, None)? };
88
89 Ok(OwnedImage {
90 device,
91 allocator: Arc::clone(alloc),
92 image_view,
93 image: VulkanImage {
94 image,
95 size,
96 format: format.into(),
97 },
98 _memory: memory,
99 max_miplevels,
100 levels: std::cmp::min(max_miplevels, size.calculate_miplevels()),
101 })
102 }
103
104 pub fn new(
105 vulkan: &VulkanObjects,
106 size: Size<u32>,
107 format: ImageFormat,
108 max_miplevels: u32,
109 ) -> error::Result<OwnedImage> {
110 Self::new_internal(
111 vulkan.device.clone(),
112 &vulkan.alloc,
113 size,
114 format,
115 max_miplevels,
116 )
117 }
118
119 pub(crate) fn scale(
120 &mut self,
121 scaling: Scale2D,
122 format: ImageFormat,
123 viewport_size: &Size<u32>,
124 source_size: &Size<u32>,
125 original_size: &Size<u32>,
126 mipmap: bool,
127 layout: Option<OwnedImageLayout>,
128 ) -> error::Result<Size<u32>> {
129 let size = source_size.scale_viewport(scaling, *viewport_size, *original_size, None);
130 if self.image.size != size
131 || (mipmap && self.max_miplevels == 1)
132 || (!mipmap && self.max_miplevels != 1)
133 || vk::Format::from(format) != self.image.format
134 {
135 let max_levels = if mipmap { u32::MAX } else { 1 };
136
137 let new = OwnedImage::new_internal(
138 self.device.clone(),
139 &self.allocator,
140 size,
141 if format == ImageFormat::Unknown {
142 ImageFormat::R8G8B8A8Unorm
143 } else {
144 format
145 },
146 max_levels,
147 )?;
148
149 let old = std::mem::replace(self, new);
150 drop(old);
151
152 if let Some(layout) = layout {
153 unsafe {
154 util::vulkan_image_layout_transition_levels(
155 &self.device,
156 layout.cmd,
157 self.image.image,
158 self.levels,
159 vk::ImageLayout::UNDEFINED,
160 layout.dst_layout,
161 vk::AccessFlags::empty(),
162 layout.dst_access,
163 layout.src_stage,
164 layout.dst_stage,
165 vk::QUEUE_FAMILY_IGNORED,
166 vk::QUEUE_FAMILY_IGNORED,
167 )
168 }
169 }
170 }
171 Ok(size)
172 }
173
174 pub(crate) fn as_input(&self, filter: FilterMode, wrap_mode: WrapMode) -> InputImage {
175 InputImage {
176 image: self.image.clone(),
177 image_view: self.image_view,
178 wrap_mode,
179 filter_mode: filter,
180 mip_filter: filter,
181 }
182 }
183
184 pub fn generate_mipmaps_and_end_pass(&self, cmd: vk::CommandBuffer) {
185 let input_barrier = vk::ImageMemoryBarrier::default()
186 .src_access_mask(vk::AccessFlags::COLOR_ATTACHMENT_WRITE)
187 .dst_access_mask(vk::AccessFlags::TRANSFER_READ)
188 .old_layout(vk::ImageLayout::COLOR_ATTACHMENT_OPTIMAL)
189 .new_layout(vk::ImageLayout::TRANSFER_SRC_OPTIMAL)
190 .src_queue_family_index(vk::QUEUE_FAMILY_IGNORED)
191 .dst_queue_family_index(vk::QUEUE_FAMILY_IGNORED)
192 .image(self.image.image)
193 .subresource_range(vk::ImageSubresourceRange {
194 aspect_mask: vk::ImageAspectFlags::COLOR,
195 base_mip_level: 0,
196 level_count: 1,
197 base_array_layer: 0,
198 layer_count: vk::REMAINING_ARRAY_LAYERS,
199 });
200
201 let mipchain_barrier = vk::ImageMemoryBarrier::default()
202 .src_access_mask(vk::AccessFlags::empty())
203 .dst_access_mask(vk::AccessFlags::TRANSFER_WRITE)
204 .old_layout(vk::ImageLayout::UNDEFINED)
205 .new_layout(vk::ImageLayout::TRANSFER_DST_OPTIMAL)
206 .src_queue_family_index(vk::QUEUE_FAMILY_IGNORED)
207 .dst_queue_family_index(vk::QUEUE_FAMILY_IGNORED)
208 .image(self.image.image)
209 .subresource_range(vk::ImageSubresourceRange {
210 aspect_mask: vk::ImageAspectFlags::COLOR,
211 base_mip_level: 1,
212 base_array_layer: 0,
213 level_count: vk::REMAINING_MIP_LEVELS,
214 layer_count: vk::REMAINING_ARRAY_LAYERS,
215 });
216
217 unsafe {
218 self.device.cmd_pipeline_barrier(
219 cmd,
220 vk::PipelineStageFlags::ALL_GRAPHICS,
221 vk::PipelineStageFlags::TRANSFER,
222 vk::DependencyFlags::empty(),
223 &[],
224 &[],
225 &[input_barrier, mipchain_barrier],
226 );
227
228 for level in 1..self.levels {
229 if level > 1 {
231 let next_barrier = vk::ImageMemoryBarrier::default()
232 .src_access_mask(vk::AccessFlags::TRANSFER_WRITE)
233 .dst_access_mask(vk::AccessFlags::TRANSFER_READ)
234 .old_layout(vk::ImageLayout::TRANSFER_DST_OPTIMAL)
235 .new_layout(vk::ImageLayout::TRANSFER_SRC_OPTIMAL)
236 .src_queue_family_index(vk::QUEUE_FAMILY_IGNORED)
237 .dst_queue_family_index(vk::QUEUE_FAMILY_IGNORED)
238 .image(self.image.image)
239 .subresource_range(vk::ImageSubresourceRange {
240 aspect_mask: vk::ImageAspectFlags::COLOR,
241 base_mip_level: level - 1,
242 base_array_layer: 0,
243 level_count: 1,
244 layer_count: vk::REMAINING_ARRAY_LAYERS,
245 });
246
247 self.device.cmd_pipeline_barrier(
248 cmd,
249 vk::PipelineStageFlags::TRANSFER,
250 vk::PipelineStageFlags::TRANSFER,
251 vk::DependencyFlags::empty(),
252 &[],
253 &[],
254 &[next_barrier],
255 );
256 }
257
258 let source_size = self.image.size.scale_mipmap(level - 1);
259 let target_size = self.image.size.scale_mipmap(level);
260
261 let src_offsets = [
262 vk::Offset3D { x: 0, y: 0, z: 0 },
263 vk::Offset3D {
264 x: source_size.width as i32,
265 y: source_size.height as i32,
266 z: 1,
267 },
268 ];
269
270 let dst_offsets = [
271 vk::Offset3D { x: 0, y: 0, z: 0 },
272 vk::Offset3D {
273 x: target_size.width as i32,
274 y: target_size.height as i32,
275 z: 1,
276 },
277 ];
278
279 let src_subresource = vk::ImageSubresourceLayers::default()
280 .aspect_mask(vk::ImageAspectFlags::COLOR)
281 .mip_level(level - 1)
282 .base_array_layer(0)
283 .layer_count(1);
284
285 let dst_subresource = vk::ImageSubresourceLayers::default()
286 .aspect_mask(vk::ImageAspectFlags::COLOR)
287 .mip_level(level)
288 .base_array_layer(0)
289 .layer_count(1);
290
291 let image_blit = vk::ImageBlit::default()
292 .src_subresource(src_subresource)
293 .src_offsets(src_offsets)
294 .dst_subresource(dst_subresource)
295 .dst_offsets(dst_offsets);
296
297 self.device.cmd_blit_image(
298 cmd,
299 self.image.image,
300 vk::ImageLayout::TRANSFER_SRC_OPTIMAL,
301 self.image.image,
302 vk::ImageLayout::TRANSFER_DST_OPTIMAL,
303 &[image_blit],
304 vk::Filter::LINEAR,
305 );
306 }
307
308 let input_barrier = vk::ImageMemoryBarrier::default()
311 .src_access_mask(vk::AccessFlags::TRANSFER_READ)
312 .dst_access_mask(vk::AccessFlags::SHADER_READ)
313 .old_layout(vk::ImageLayout::TRANSFER_SRC_OPTIMAL)
314 .new_layout(vk::ImageLayout::SHADER_READ_ONLY_OPTIMAL)
315 .src_queue_family_index(vk::QUEUE_FAMILY_IGNORED)
316 .dst_queue_family_index(vk::QUEUE_FAMILY_IGNORED)
317 .image(self.image.image)
318 .subresource_range(vk::ImageSubresourceRange {
319 aspect_mask: vk::ImageAspectFlags::COLOR,
320 base_mip_level: 0,
321 level_count: self.levels - 1,
322 base_array_layer: 0,
323 layer_count: vk::REMAINING_ARRAY_LAYERS,
324 });
325
326 let mipchain_barrier = vk::ImageMemoryBarrier::default()
327 .src_access_mask(vk::AccessFlags::TRANSFER_WRITE)
328 .dst_access_mask(vk::AccessFlags::SHADER_READ)
329 .old_layout(vk::ImageLayout::TRANSFER_DST_OPTIMAL)
330 .new_layout(vk::ImageLayout::SHADER_READ_ONLY_OPTIMAL)
331 .src_queue_family_index(vk::QUEUE_FAMILY_IGNORED)
332 .dst_queue_family_index(vk::QUEUE_FAMILY_IGNORED)
333 .image(self.image.image)
334 .subresource_range(vk::ImageSubresourceRange {
335 aspect_mask: vk::ImageAspectFlags::COLOR,
336 base_mip_level: self.levels - 1,
337 base_array_layer: 0,
338 level_count: 1,
339 layer_count: vk::REMAINING_ARRAY_LAYERS,
340 });
341
342 self.device.cmd_pipeline_barrier(
345 cmd,
346 vk::PipelineStageFlags::TRANSFER,
347 vk::PipelineStageFlags::FRAGMENT_SHADER,
348 vk::DependencyFlags::empty(),
349 &[],
350 &[],
351 &[input_barrier, mipchain_barrier],
352 );
353 }
354 }
355
356 pub unsafe fn copy_from(
358 &self,
359 cmd: vk::CommandBuffer,
360 source: &VulkanImage,
361 source_layout: vk::ImageLayout,
362 ) {
363 let region = vk::ImageCopy::default()
364 .src_subresource(
365 vk::ImageSubresourceLayers::default()
366 .aspect_mask(vk::ImageAspectFlags::COLOR)
367 .mip_level(0)
368 .base_array_layer(0)
369 .layer_count(1),
370 )
371 .dst_subresource(
372 vk::ImageSubresourceLayers::default()
373 .aspect_mask(vk::ImageAspectFlags::COLOR)
374 .mip_level(0)
375 .base_array_layer(0)
376 .layer_count(1),
377 )
378 .src_offset(Default::default())
379 .dst_offset(Default::default())
380 .extent(source.size.into());
381
382 unsafe {
383 util::vulkan_image_layout_transition_levels(
384 &self.device,
385 cmd,
386 self.image.image,
387 vk::REMAINING_MIP_LEVELS,
388 vk::ImageLayout::UNDEFINED,
389 vk::ImageLayout::TRANSFER_DST_OPTIMAL,
390 vk::AccessFlags::empty(),
391 vk::AccessFlags::TRANSFER_WRITE,
392 vk::PipelineStageFlags::FRAGMENT_SHADER,
393 vk::PipelineStageFlags::TRANSFER,
394 vk::QUEUE_FAMILY_IGNORED,
395 vk::QUEUE_FAMILY_IGNORED,
396 );
397
398 self.device.cmd_copy_image(
399 cmd,
400 source.image,
401 source_layout,
402 self.image.image,
403 vk::ImageLayout::TRANSFER_DST_OPTIMAL,
404 &[region],
405 );
406 util::vulkan_image_layout_transition_levels(
407 &self.device,
408 cmd,
409 self.image.image,
410 vk::REMAINING_MIP_LEVELS,
411 vk::ImageLayout::TRANSFER_DST_OPTIMAL,
412 vk::ImageLayout::SHADER_READ_ONLY_OPTIMAL,
413 vk::AccessFlags::TRANSFER_WRITE,
414 vk::AccessFlags::SHADER_READ,
415 vk::PipelineStageFlags::TRANSFER,
416 vk::PipelineStageFlags::FRAGMENT_SHADER,
417 vk::QUEUE_FAMILY_IGNORED,
418 vk::QUEUE_FAMILY_IGNORED,
419 );
420 }
421 }
422
423 pub fn clear(&self, cmd: vk::CommandBuffer) {
424 unsafe {
425 util::vulkan_image_layout_transition_levels(
426 &self.device,
427 cmd,
428 self.image.image,
429 vk::REMAINING_MIP_LEVELS,
430 vk::ImageLayout::UNDEFINED,
431 vk::ImageLayout::TRANSFER_DST_OPTIMAL,
432 vk::AccessFlags::empty(),
433 vk::AccessFlags::TRANSFER_WRITE,
434 vk::PipelineStageFlags::TOP_OF_PIPE,
435 vk::PipelineStageFlags::TRANSFER,
436 vk::QUEUE_FAMILY_IGNORED,
437 vk::QUEUE_FAMILY_IGNORED,
438 );
439 self.device.cmd_clear_color_image(
440 cmd,
441 self.image.image,
442 vk::ImageLayout::TRANSFER_DST_OPTIMAL,
443 &vk::ClearColorValue {
444 float32: [0.0, 0.0, 0.0, 0.0],
445 },
446 &[vk::ImageSubresourceRange::default()
447 .aspect_mask(vk::ImageAspectFlags::COLOR)
448 .base_mip_level(0)
449 .level_count(1)
450 .base_array_layer(0)
451 .layer_count(1)],
452 );
453
454 util::vulkan_image_layout_transition_levels(
455 &self.device,
456 cmd,
457 self.image.image,
458 vk::REMAINING_MIP_LEVELS,
459 vk::ImageLayout::TRANSFER_DST_OPTIMAL,
460 vk::ImageLayout::SHADER_READ_ONLY_OPTIMAL,
461 vk::AccessFlags::TRANSFER_WRITE,
462 vk::AccessFlags::SHADER_READ,
463 vk::PipelineStageFlags::TRANSFER,
464 vk::PipelineStageFlags::FRAGMENT_SHADER,
465 vk::QUEUE_FAMILY_IGNORED,
466 vk::QUEUE_FAMILY_IGNORED,
467 );
468 }
469 }
470}
471
472impl Drop for OwnedImage {
473 fn drop(&mut self) {
474 unsafe {
475 if self.image_view != vk::ImageView::null() {
476 self.device.destroy_image_view(self.image_view, None);
477 }
478 if self.image.image != vk::Image::null() {
479 self.device.destroy_image(self.image.image, None);
480 }
481 }
482 }
483}
484
485#[derive(Clone)]
487pub struct VulkanImage {
488 pub image: vk::Image,
490 pub size: Size<u32>,
492 pub format: vk::Format,
494}
495
496#[derive(Clone)]
497pub struct InputImage {
498 pub image: VulkanImage,
500 pub image_view: vk::ImageView,
502 pub wrap_mode: WrapMode,
503 pub filter_mode: FilterMode,
504 pub mip_filter: FilterMode,
505}
506
507impl AsRef<InputImage> for InputImage {
508 fn as_ref(&self) -> &InputImage {
509 self
510 }
511}
512
513impl ScaleFramebuffer for OwnedImage {
514 type Error = FilterChainError;
515 type Context = Option<OwnedImageLayout>;
516
517 fn scale(
518 &mut self,
519 scaling: Scale2D,
520 format: ImageFormat,
521 viewport_size: &Size<u32>,
522 source_size: &Size<u32>,
523 original_size: &Size<u32>,
524 should_mipmap: bool,
525 context: &Self::Context,
526 ) -> Result<Size<u32>, Self::Error> {
527 self.scale(
528 scaling,
529 format,
530 viewport_size,
531 source_size,
532 original_size,
533 should_mipmap,
534 context.clone(),
535 )
536 }
537}
538
539impl GetSize<u32> for VulkanImage {
540 type Error = std::convert::Infallible;
541
542 fn size(&self) -> Result<Size<u32>, Self::Error> {
543 Ok(self.size)
544 }
545}