2024-02-02 10:03:21 +11:00
|
|
|
use std::ops::Deref;
|
2023-12-16 22:28:41 +11:00
|
|
|
use std::sync::Arc;
|
2024-02-02 10:03:21 +11:00
|
|
|
use wgpu::{TextureFormat, TextureView};
|
2023-12-16 22:28:41 +11:00
|
|
|
use librashader_common::{FilterMode, ImageFormat, Size, WrapMode};
|
|
|
|
use librashader_presets::Scale2D;
|
2024-02-02 10:03:21 +11:00
|
|
|
use librashader_runtime::scaling::{MipmapSize, ScaleFramebuffer, ViewportSize};
|
|
|
|
use crate::error::FilterChainError;
|
2023-12-16 22:28:41 +11:00
|
|
|
|
|
|
|
pub struct OwnedImage {
|
|
|
|
device: Arc<wgpu::Device>,
|
2024-02-02 10:03:21 +11:00
|
|
|
pub image: Arc<wgpu::Texture>,
|
|
|
|
pub view: Arc<wgpu::TextureView>,
|
2023-12-16 22:28:41 +11:00
|
|
|
pub max_miplevels: u32,
|
|
|
|
pub levels: u32,
|
|
|
|
pub size: Size<u32>,
|
|
|
|
}
|
|
|
|
|
2024-02-02 10:03:21 +11:00
|
|
|
pub enum Handle<'a, T> {
|
|
|
|
Borrowed(&'a T),
|
|
|
|
Owned(Arc<T>)
|
|
|
|
}
|
|
|
|
|
|
|
|
impl<T> Clone for Handle<'_, T> {
|
|
|
|
fn clone(&self) -> Self {
|
|
|
|
match self {
|
|
|
|
Handle::Borrowed(r) => Handle::Borrowed(r),
|
|
|
|
Handle::Owned(r) => Handle::Owned(Arc::clone(r))
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
impl<T> Deref for Handle<'_, T> {
|
|
|
|
type Target = T;
|
|
|
|
|
|
|
|
fn deref(&self) -> &Self::Target {
|
|
|
|
match self {
|
|
|
|
Handle::Borrowed(r) => &r,
|
|
|
|
Handle::Owned(r) => &r
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
#[derive(Clone)]
|
2023-12-16 22:28:41 +11:00
|
|
|
pub struct InputImage {
|
|
|
|
/// A handle to the `VkImage`.
|
2024-02-02 10:03:21 +11:00
|
|
|
pub image: Arc<wgpu::Texture>,
|
|
|
|
pub view: Arc<wgpu::TextureView>,
|
2023-12-16 22:28:41 +11:00
|
|
|
pub wrap_mode: WrapMode,
|
|
|
|
pub filter_mode: FilterMode,
|
|
|
|
pub mip_filter: FilterMode,
|
|
|
|
}
|
|
|
|
|
2024-02-02 10:03:21 +11:00
|
|
|
impl AsRef<InputImage> for InputImage {
|
|
|
|
fn as_ref(&self) -> &InputImage {
|
|
|
|
&self
|
|
|
|
}
|
|
|
|
}
|
2023-12-16 22:28:41 +11:00
|
|
|
|
|
|
|
impl OwnedImage {
|
|
|
|
pub fn new(device: Arc<wgpu::Device>,
|
|
|
|
size: Size<u32>,
|
|
|
|
max_miplevels: u32,
|
|
|
|
format: ImageFormat,
|
|
|
|
) -> Self {
|
|
|
|
|
|
|
|
let format: Option<wgpu::TextureFormat> = format.into();
|
|
|
|
let format = format.unwrap_or(wgpu::TextureFormat::Rgba8Unorm);
|
|
|
|
|
|
|
|
let texture = device.create_texture(&wgpu::TextureDescriptor {
|
|
|
|
label: None,
|
|
|
|
size: size.into(),
|
|
|
|
mip_level_count: std::cmp::min(max_miplevels, size.calculate_miplevels()),
|
|
|
|
sample_count: 1,
|
|
|
|
dimension: wgpu::TextureDimension::D2,
|
|
|
|
format,
|
|
|
|
usage: wgpu::TextureUsages::TEXTURE_BINDING
|
|
|
|
| wgpu::TextureUsages::RENDER_ATTACHMENT
|
|
|
|
| wgpu::TextureUsages::COPY_DST
|
|
|
|
| wgpu::TextureUsages::COPY_SRC,
|
|
|
|
view_formats: &[format.into()],
|
|
|
|
});
|
|
|
|
|
|
|
|
let view = texture.create_view(&wgpu::TextureViewDescriptor {
|
|
|
|
label: None,
|
|
|
|
format: Some(format),
|
|
|
|
dimension: Some(wgpu::TextureViewDimension::D2),
|
|
|
|
aspect: wgpu::TextureAspect::All,
|
|
|
|
base_mip_level: 0,
|
|
|
|
mip_level_count: None,
|
|
|
|
base_array_layer: 0,
|
|
|
|
array_layer_count: None,
|
|
|
|
});
|
|
|
|
|
|
|
|
Self {
|
|
|
|
device,
|
2024-02-02 10:03:21 +11:00
|
|
|
image: Arc::new(texture),
|
|
|
|
view: Arc::new(view),
|
2023-12-16 22:28:41 +11:00
|
|
|
max_miplevels,
|
|
|
|
levels: std::cmp::min(max_miplevels, size.calculate_miplevels()),
|
|
|
|
size,
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
pub fn scale(
|
|
|
|
&mut self,
|
|
|
|
scaling: Scale2D,
|
|
|
|
format: ImageFormat,
|
|
|
|
viewport_size: &Size<u32>,
|
|
|
|
source_size: &Size<u32>,
|
|
|
|
mipmap: bool,
|
|
|
|
) -> Size<u32> {
|
|
|
|
let size = source_size.scale_viewport(scaling, *viewport_size);
|
|
|
|
let format: Option<wgpu::TextureFormat> = format.into();
|
|
|
|
let format = format.unwrap_or(wgpu::TextureFormat::Rgba8Unorm);
|
|
|
|
|
|
|
|
if self.size != size
|
|
|
|
|| (mipmap && self.max_miplevels == 1)
|
|
|
|
|| (!mipmap && self.max_miplevels != 1)
|
2024-02-02 16:51:17 +11:00
|
|
|
|| format != self.image.format()
|
2023-12-16 22:28:41 +11:00
|
|
|
{
|
|
|
|
let mut new = OwnedImage::new(Arc::clone(&self.device), size, self.max_miplevels, format.into());
|
|
|
|
std::mem::swap(self, &mut new);
|
|
|
|
}
|
|
|
|
size
|
|
|
|
}
|
2024-01-26 12:05:31 +11:00
|
|
|
|
|
|
|
pub(crate) fn as_input(&self, filter: FilterMode, wrap_mode: WrapMode) -> InputImage {
|
|
|
|
InputImage {
|
2024-02-02 10:03:21 +11:00
|
|
|
image: Arc::clone(&self.image),
|
|
|
|
view: Arc::clone(&self.view),
|
2024-01-26 12:05:31 +11:00
|
|
|
wrap_mode,
|
|
|
|
filter_mode: filter,
|
|
|
|
mip_filter: filter,
|
|
|
|
}
|
|
|
|
}
|
2024-02-02 10:03:21 +11:00
|
|
|
}
|
|
|
|
|
|
|
|
impl ScaleFramebuffer for OwnedImage {
|
|
|
|
type Error = FilterChainError;
|
|
|
|
type Context = ();
|
2024-01-26 12:05:31 +11:00
|
|
|
|
2024-02-02 10:03:21 +11:00
|
|
|
fn scale(&mut self,
|
|
|
|
scaling: Scale2D,
|
|
|
|
format: ImageFormat,
|
|
|
|
viewport_size: &Size<u32>,
|
|
|
|
source_size: &Size<u32>,
|
|
|
|
should_mipmap: bool,
|
|
|
|
_context: &Self::Context) -> Result<Size<u32>, Self::Error> {
|
|
|
|
Ok(self.scale(
|
|
|
|
scaling,
|
|
|
|
format,
|
|
|
|
viewport_size,
|
|
|
|
source_size,
|
|
|
|
should_mipmap,
|
|
|
|
))
|
|
|
|
}
|
2023-12-16 22:28:41 +11:00
|
|
|
}
|