Skip to content

Commit

Permalink
Merge pull request #292 from NoiseStudio/feature/281/decode-encode-te…
Browse files Browse the repository at this point in the history
…xture

Decode and encode Texture2D from webp, png, jpg formats
  • Loading branch information
kkard2 committed Jun 3, 2023
2 parents e11c1ea + 80c0b80 commit a702c5b
Show file tree
Hide file tree
Showing 24 changed files with 1,147 additions and 2 deletions.
3 changes: 3 additions & 0 deletions NoiseEngine.Native/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,9 @@ arc-cell = "0.3.3"
const-utf16 = "0.2.1"
cgmath = "0.18.0"
crossbeam-queue = "0.3.8"
anyhow = "1.0.71"
image = "0.24.6"
webp = "0.2.2"

[dependencies.uuid]
version = "1.2.2"
Expand Down
63 changes: 63 additions & 0 deletions NoiseEngine.Native/src/interop/rendering/cpu_texture_interop.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
use ash::vk;

use crate::{
interop::prelude::{
InteropReadOnlySpan,
InteropResult,
ResultError,
ResultErrorKind, InteropOption, InteropArray,
},
rendering::{cpu_texture_2d::{CpuTextureData, self}, cpu_texture_2d_encoding}
};

#[no_mangle]
extern "C" fn rendering_cpu_texture_interop_decode(
file_data: InteropReadOnlySpan<u8>,
format: InteropOption<vk::Format>,
) -> InteropResult<CpuTextureData> {
let result =
cpu_texture_2d_encoding::decode(file_data.into(), format.into());

match result {
Ok(data) => {
InteropResult::with_ok(data)
},
Err(error) => {
InteropResult::with_err(ResultError::with_kind(
&*Box::<dyn std::error::Error>::from(error),
ResultErrorKind::Argument,
))
},
}
}

#[no_mangle]
extern "C" fn rendering_cpu_texture_interop_encode(
data: InteropReadOnlySpan<u8>,
width: u32,
height: u32,
format: vk::Format,
file_format: cpu_texture_2d::TextureFileFormat,
quality: InteropOption<u8>,
) -> InteropResult<InteropArray<u8>> {
let result = cpu_texture_2d_encoding::encode(
data.into(),
width,
height,
format,
file_format,
quality.into(),
);

match result {
Ok(data) => {
InteropResult::with_ok(data.into())
},
Err(error) => {
InteropResult::with_err(ResultError::with_kind(
&*Box::<dyn std::error::Error>::from(error),
ResultErrorKind::Argument,
))
},
}
}
1 change: 1 addition & 0 deletions NoiseEngine.Native/src/interop/rendering/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,3 +4,4 @@ pub mod vulkan;

pub mod fence_interop;
pub mod texture_interop;
pub mod cpu_texture_interop;
1 change: 1 addition & 0 deletions NoiseEngine.Native/src/interop/result_error_kind.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ pub enum ResultErrorKind {
NullReference = 2,
InvalidOperation = 3,
Overflow = 4,
Argument = 5,

GraphicsUniversal = 1000,
GraphicsInstanceCreate = 1001,
Expand Down
142 changes: 142 additions & 0 deletions NoiseEngine.Native/src/rendering/cpu_texture_2d.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,142 @@
use ash::vk;

use crate::interop::prelude::InteropArray;

#[repr(C)]
pub enum TextureFileFormat {
Png,
Jpeg,
WebP
}

pub fn vk_format_to_color_type(
vk_format: vk::Format,
) -> Option<image::ColorType> {
type F = vk::Format;

match vk_format {
F::R8_UNORM | F::R8_SNORM | F::R8_USCALED | F::R8_SSCALED | F::R8_UINT | F::R8_SINT | F::R8_SRGB => {
Some(image::ColorType::L8)
},
F::R8G8_UNORM | F::R8G8_SNORM | F::R8G8_USCALED | F::R8G8_SSCALED | F::R8G8_UINT | F::R8G8_SINT | F::R8G8_SRGB => {
Some(image::ColorType::La8)
},
F::R8G8B8_UNORM | F::R8G8B8_SNORM | F::R8G8B8_USCALED | F::R8G8B8_SSCALED | F::R8G8B8_UINT | F::R8G8B8_SINT | F::R8G8B8_SRGB => {
Some(image::ColorType::Rgb8)
},
F::R8G8B8A8_UNORM | F::R8G8B8A8_SNORM | F::R8G8B8A8_USCALED | F::R8G8B8A8_SSCALED | F::R8G8B8A8_UINT | F::R8G8B8A8_SINT | F::R8G8B8A8_SRGB => {
Some(image::ColorType::Rgba8)
},
F::R16_UNORM | F::R16_SNORM | F::R16_USCALED | F::R16_SSCALED | F::R16_UINT | F::R16_SINT => {
Some(image::ColorType::L16)
},
F::R16G16_UNORM | F::R16G16_SNORM | F::R16G16_USCALED | F::R16G16_SSCALED | F::R16G16_UINT | F::R16G16_SINT => {
Some(image::ColorType::La16)
},
F::R16G16B16_UNORM | F::R16G16B16_SNORM | F::R16G16B16_USCALED | F::R16G16B16_SSCALED | F::R16G16B16_UINT | F::R16G16B16_SINT => {
Some(image::ColorType::Rgb16)
},
F::R16G16B16A16_UNORM | F::R16G16B16A16_SNORM | F::R16G16B16A16_USCALED | F::R16G16B16A16_SSCALED | F::R16G16B16A16_UINT | F::R16G16B16A16_SINT => {
Some(image::ColorType::Rgba16)
},
F::R32G32B32_SFLOAT => {
Some(image::ColorType::Rgb32F)
},
F::R32G32B32A32_SFLOAT => {
Some(image::ColorType::Rgba32F)
},
_ => None,
}
}

#[repr(C)]
pub struct CpuTextureData {
extent_x: u32,
extent_y: u32,
extent_z: u32,
format: vk::Format,
data: InteropArray<u8>,
}

impl CpuTextureData {
pub fn new(
extent_x: u32,
extent_y: u32,
extent_z: u32,
format: vk::Format,
data: InteropArray<u8>,
) -> Self {
assert_ne!(extent_x, 0);
assert_ne!(extent_y, 0);
assert_ne!(extent_z, 0);
let size =
extent_x * extent_y * extent_z * Self::pixel_size(format) as u32;
assert_eq!(size, data.as_slice().len() as u32);

Self {
extent_x,
extent_y,
extent_z,
format,
data,
}
}

pub fn extent_x(&self) -> u32 {
self.extent_x
}

pub fn extent_y(&self) -> u32 {
self.extent_y
}

pub fn extent_z(&self) -> u32 {
self.extent_z
}

pub fn format(&self) -> &vk::Format {
&self.format
}

pub fn data(&self) -> &InteropArray<u8> {
&self.data
}

pub fn pixel_size(format: vk::Format) -> usize {
type F = vk::Format;

match format {
F::R8_UNORM | F::R8_SNORM | F::R8_USCALED | F::R8_SSCALED | F::R8_UINT | F::R8_SINT | F::R8_SRGB => {
1
},
F::R8G8_UNORM | F::R8G8_SNORM | F::R8G8_USCALED | F::R8G8_SSCALED | F::R8G8_UINT | F::R8G8_SINT | F::R8G8_SRGB => {
2
},
F::R8G8B8_UNORM | F::R8G8B8_SNORM | F::R8G8B8_USCALED | F::R8G8B8_SSCALED | F::R8G8B8_UINT | F::R8G8B8_SINT | F::R8G8B8_SRGB => {
3
},
F::R8G8B8A8_UNORM | F::R8G8B8A8_SNORM | F::R8G8B8A8_USCALED | F::R8G8B8A8_SSCALED | F::R8G8B8A8_UINT | F::R8G8B8A8_SINT | F::R8G8B8A8_SRGB => {
4
},
F::R16_UNORM | F::R16_SNORM | F::R16_USCALED | F::R16_SSCALED | F::R16_UINT | F::R16_SINT => {
2
},
F::R16G16_UNORM | F::R16G16_SNORM | F::R16G16_USCALED | F::R16G16_SSCALED | F::R16G16_UINT | F::R16G16_SINT => {
4
},
F::R16G16B16_UNORM | F::R16G16B16_SNORM | F::R16G16B16_USCALED | F::R16G16B16_SSCALED | F::R16G16B16_UINT | F::R16G16B16_SINT => {
6
},
F::R16G16B16A16_UNORM | F::R16G16B16A16_SNORM | F::R16G16B16A16_USCALED | F::R16G16B16A16_SSCALED | F::R16G16B16A16_UINT | F::R16G16B16A16_SINT => {
8
},
F::R32G32B32_SFLOAT => {
12
},
F::R32G32B32A32_SFLOAT => {
16
},
_ => unimplemented!("unsupported format: {:?}", format),
}
}
}
Loading

0 comments on commit a702c5b

Please sign in to comment.