librashader/librashader-runtime-wgpu/src/texture.rs

171 lines
4.8 KiB
Rust
Raw Normal View History

use crate::error::FilterChainError;
use librashader_common::{FilterMode, ImageFormat, Size, WrapMode};
use librashader_presets::Scale2D;
use librashader_runtime::scaling::{MipmapSize, ScaleFramebuffer, ViewportSize};
use std::ops::Deref;
use std::sync::Arc;
use wgpu::{ImageCopyTexture, TextureFormat, TextureView};
pub struct OwnedImage {
device: Arc<wgpu::Device>,
pub image: Arc<wgpu::Texture>,
pub view: Arc<wgpu::TextureView>,
pub max_miplevels: u32,
pub levels: u32,
pub size: Size<u32>,
}
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)]
pub struct InputImage {
/// A handle to the `VkImage`.
pub image: Arc<wgpu::Texture>,
pub view: Arc<wgpu::TextureView>,
pub wrap_mode: WrapMode,
pub filter_mode: FilterMode,
pub mip_filter: FilterMode,
}
impl AsRef<InputImage> for InputImage {
fn as_ref(&self) -> &InputImage {
&self
}
}
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,
image: Arc::new(texture),
view: Arc::new(view),
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)
|| format != self.image.format()
{
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 {
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,
}
}
pub fn copy_from(&self, cmd: &mut wgpu::CommandEncoder, source: &wgpu::Texture) {
cmd.copy_texture_to_texture(
source.as_image_copy(),
self.image.as_image_copy(),
source.size(),
)
}
pub fn clear(&self, cmd: &mut wgpu::CommandEncoder) {
cmd.clear_texture(&self.image, &wgpu::ImageSubresourceRange::default());
}
pub fn generate_mipmaps(&self, cmd: &mut wgpu::CommandEncoder) {}
}
impl ScaleFramebuffer for OwnedImage {
type Error = FilterChainError;
type Context = ();
2024-01-26 12:05:31 +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))
}
}