diff --git a/Cargo.lock b/Cargo.lock index 6e108702..485b5c42 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -179,7 +179,7 @@ version = "0.1.0" dependencies = [ "foreign-types 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)", "gl 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)", - "metal 0.14.0 (registry+https://github.com/rust-lang/crates.io-index)", + "metal 0.17.1 (registry+https://github.com/rust-lang/crates.io-index)", "objc 0.2.7 (registry+https://github.com/rust-lang/crates.io-index)", "pathfinder_canvas 0.1.0", "pathfinder_content 0.1.0", @@ -530,7 +530,7 @@ dependencies = [ "foreign-types 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)", "gl 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)", "jemallocator 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)", - "metal 0.14.0 (registry+https://github.com/rust-lang/crates.io-index)", + "metal 0.17.1 (registry+https://github.com/rust-lang/crates.io-index)", "nfd 0.0.4 (registry+https://github.com/rust-lang/crates.io-index)", "pathfinder_demo 0.1.0", "pathfinder_geometry 0.3.0", @@ -1257,23 +1257,6 @@ dependencies = [ "rustc_version 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)", ] -[[package]] -name = "metal" -version = "0.14.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "bitflags 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)", - "block 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", - "cocoa 0.18.5 (registry+https://github.com/rust-lang/crates.io-index)", - "core-graphics 0.17.3 (registry+https://github.com/rust-lang/crates.io-index)", - "foreign-types 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.65 (registry+https://github.com/rust-lang/crates.io-index)", - "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", - "objc 0.2.7 (registry+https://github.com/rust-lang/crates.io-index)", - "objc-foundation 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", - "objc_id 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", -] - [[package]] name = "metal" version = "0.17.1" @@ -1406,16 +1389,6 @@ dependencies = [ "objc_exception 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", ] -[[package]] -name = "objc-foundation" -version = "0.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "block 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", - "objc 0.2.7 (registry+https://github.com/rust-lang/crates.io-index)", - "objc_id 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", -] - [[package]] name = "objc_exception" version = "0.1.1" @@ -1424,14 +1397,6 @@ dependencies = [ "gcc 0.3.55 (registry+https://github.com/rust-lang/crates.io-index)", ] -[[package]] -name = "objc_id" -version = "0.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "objc 0.2.7 (registry+https://github.com/rust-lang/crates.io-index)", -] - [[package]] name = "ordered-float" version = "1.0.2" @@ -1524,7 +1489,7 @@ dependencies = [ "foreign-types 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)", "gl 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)", "libc 0.2.65 (registry+https://github.com/rust-lang/crates.io-index)", - "metal 0.14.0 (registry+https://github.com/rust-lang/crates.io-index)", + "metal 0.17.1 (registry+https://github.com/rust-lang/crates.io-index)", "pathfinder_canvas 0.1.0", "pathfinder_content 0.1.0", "pathfinder_geometry 0.3.0", @@ -1567,7 +1532,7 @@ dependencies = [ "gl 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)", "image 0.21.3 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", - "metal 0.14.0 (registry+https://github.com/rust-lang/crates.io-index)", + "metal 0.17.1 (registry+https://github.com/rust-lang/crates.io-index)", "pathfinder_content 0.1.0", "pathfinder_export 0.1.0", "pathfinder_geometry 0.3.0", @@ -1605,6 +1570,7 @@ name = "pathfinder_gl" version = "0.1.0" dependencies = [ "gl 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)", + "half 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", "pathfinder_geometry 0.3.0", "pathfinder_gpu 0.1.0", @@ -1615,6 +1581,7 @@ dependencies = [ name = "pathfinder_gpu" version = "0.1.0" dependencies = [ + "half 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)", "image 0.21.3 (registry+https://github.com/rust-lang/crates.io-index)", "pathfinder_content 0.1.0", "pathfinder_geometry 0.3.0", @@ -1662,6 +1629,7 @@ dependencies = [ "cocoa 0.19.1 (registry+https://github.com/rust-lang/crates.io-index)", "core-foundation 0.6.4 (registry+https://github.com/rust-lang/crates.io-index)", "foreign-types 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)", + "half 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)", "metal 0.17.1 (registry+https://github.com/rust-lang/crates.io-index)", "objc 0.2.7 (registry+https://github.com/rust-lang/crates.io-index)", "pathfinder_geometry 0.3.0", @@ -2919,7 +2887,6 @@ source = "registry+https://github.com/rust-lang/crates.io-index" "checksum memchr 2.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "88579771288728879b57485cc7d6b07d648c9f0141eb955f8ab7f9d45394468e" "checksum memmap 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "6585fd95e7bb50d6cc31e20d4cf9afb4e2ba16c5846fc76793f11218da9c475b" "checksum memoffset 0.5.3 (registry+https://github.com/rust-lang/crates.io-index)" = "75189eb85871ea5c2e2c15abbdd541185f63b408415e5051f5cac122d8c774b9" -"checksum metal 0.14.0 (registry+https://github.com/rust-lang/crates.io-index)" = "cd3f21d259068945192293b7a98b1c6844af9eb7602e393c405198b229efc157" "checksum metal 0.17.1 (registry+https://github.com/rust-lang/crates.io-index)" = "f83c7dcc2038e12f68493fa3de44235df27b2497178e257185b4b5b5d028a1e4" "checksum nfd 0.0.4 (registry+https://github.com/rust-lang/crates.io-index)" = "8e752e3c216bc8a491c5b59fa46da10f1379ae450b19ac688e07f4bb55042e98" "checksum nix 0.14.1 (registry+https://github.com/rust-lang/crates.io-index)" = "6c722bee1037d430d0f8e687bbdbf222f27cc6e4e68d5caf630857bb2b6dbdce" @@ -2934,9 +2901,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" "checksum num-traits 0.2.9 (registry+https://github.com/rust-lang/crates.io-index)" = "443c53b3c3531dfcbfa499d8893944db78474ad7a1d87fa2d94d1a2231693ac6" "checksum num_cpus 1.11.1 (registry+https://github.com/rust-lang/crates.io-index)" = "76dac5ed2a876980778b8b85f75a71b6cbf0db0b1232ee12f826bccb00d09d72" "checksum objc 0.2.7 (registry+https://github.com/rust-lang/crates.io-index)" = "915b1b472bc21c53464d6c8461c9d3af805ba1ef837e1cac254428f4a77177b1" -"checksum objc-foundation 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "1add1b659e36c9607c7aab864a76c7a4c2760cd0cd2e120f3fb8b952c7e22bf9" "checksum objc_exception 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "098cd29a2fa3c230d3463ae069cecccc3fdfd64c0d2496ab5b96f82dab6a00dc" -"checksum objc_id 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "c92d4ddb4bd7b50d730c215ff871754d0da6b2178849f8a2a2ab69712d0c073b" "checksum ordered-float 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)" = "18869315e81473c951eb56ad5558bbc56978562d3ecfb87abb7a1e944cea4518" "checksum osmesa-sys 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "88cfece6e95d2e717e0872a7f53a8684712ad13822a7979bc760b9c77ec0013b" "checksum owning_ref 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "49a4b8ea2179e6a2e27411d3bca09ca6dd630821cf6894c6c7c8467a8ee7ef13" diff --git a/c/Cargo.toml b/c/Cargo.toml index bf51584f..80fae46a 100644 --- a/c/Cargo.toml +++ b/c/Cargo.toml @@ -37,7 +37,7 @@ path = "../renderer" path = "../simd" [target.'cfg(target_os = "macos")'.dependencies] -metal = "0.14" +metal = "0.17" [target.'cfg(target_os = "macos")'.dependencies.pathfinder_metal] path = "../metal" diff --git a/demo/common/Cargo.toml b/demo/common/Cargo.toml index bf6a270b..74cd9d16 100644 --- a/demo/common/Cargo.toml +++ b/demo/common/Cargo.toml @@ -50,7 +50,7 @@ path = "../../svg" path = "../../ui" [target.'cfg(target_os = "macos")'.dependencies] -metal = "0.14" +metal = "0.17" [target.'cfg(target_os = "macos")'.dependencies.pathfinder_metal] path = "../../metal" diff --git a/demo/common/src/renderer.rs b/demo/common/src/renderer.rs index 88e0a73c..b2205f8d 100644 --- a/demo/common/src/renderer.rs +++ b/demo/common/src/renderer.rs @@ -298,7 +298,7 @@ impl DemoApp where W: Window { let viewport = RectI::new(Vector2I::default(), drawable_size); let pixels = match self.renderer.device.read_pixels(&RenderTarget::Default, viewport) { TextureData::U8(pixels) => pixels, - TextureData::U16(_) => panic!("Unexpected pixel format for default framebuffer!"), + _ => panic!("Unexpected pixel format for default framebuffer!"), }; image::save_buffer( path, diff --git a/demo/native/Cargo.toml b/demo/native/Cargo.toml index 05c33dd3..d1040452 100644 --- a/demo/native/Cargo.toml +++ b/demo/native/Cargo.toml @@ -33,7 +33,7 @@ path = "../../simd" [target.'cfg(target_os = "macos")'.dependencies] foreign-types = "0.3" -metal = "0.14" +metal = "0.17" [target.'cfg(target_os = "macos")'.dependencies.pathfinder_metal] path = "../../metal" diff --git a/examples/canvas_metal_minimal/Cargo.toml b/examples/canvas_metal_minimal/Cargo.toml index 9950a900..91d7fc1d 100644 --- a/examples/canvas_metal_minimal/Cargo.toml +++ b/examples/canvas_metal_minimal/Cargo.toml @@ -7,7 +7,7 @@ edition = "2018" [dependencies] foreign-types = "0.3" gl = "0.6" -metal = "0.14" +metal = "0.17" objc = "0.2" sdl2 = "0.32" sdl2-sys = "0.32" diff --git a/gl/Cargo.toml b/gl/Cargo.toml index 88befe8d..f505bab0 100644 --- a/gl/Cargo.toml +++ b/gl/Cargo.toml @@ -9,6 +9,7 @@ crate-type = ["rlib", "staticlib"] [dependencies] gl = "0.6" +half = "1.4" [dependencies.log] version = "0.4" diff --git a/gl/src/lib.rs b/gl/src/lib.rs index 3e770c63..1e8f5d4a 100644 --- a/gl/src/lib.rs +++ b/gl/src/lib.rs @@ -14,6 +14,7 @@ extern crate log; use gl::types::{GLboolean, GLchar, GLenum, GLfloat, GLint, GLsizei, GLsizeiptr, GLuint, GLvoid}; +use half::f16; use pathfinder_geometry::rect::RectI; use pathfinder_geometry::vector::Vector2I; use pathfinder_gpu::resources::ResourceLoader; @@ -256,25 +257,7 @@ impl Device for GLDevice { fn create_texture_from_data(&self, format: TextureFormat, size: Vector2I, data: TextureDataRef) -> GLTexture { - let channels = match (format, data) { - (TextureFormat::R8, TextureDataRef::U8(_)) => 1, - (TextureFormat::RGBA8, TextureDataRef::U8(_)) => 4, - (TextureFormat::RGBA32F, TextureDataRef::F32(_)) => 4, - _ => panic!("Unimplemented texture format in `create_texture_from_data`!"), - }; - - let area = size.x() as usize * size.y() as usize; - let data_ptr = match data { - TextureDataRef::U8(data) => { - assert!(data.len() >= area * channels); - data.as_ptr() as *const GLvoid - } - TextureDataRef::F32(data) => { - assert!(data.len() >= area * channels); - data.as_ptr() as *const GLvoid - } - }; - + let data_ptr = data.check_and_extract_data_ptr(size, format); let mut texture = GLTexture { gl_texture: 0, size, format: TextureFormat::R8 }; unsafe { gl::GenTextures(1, &mut texture.gl_texture); ck(); @@ -489,20 +472,37 @@ impl Device for GLDevice { texture.size } - fn upload_to_texture(&self, texture: &Self::Texture, size: Vector2I, data: &[u8]) { - // FIXME(pcwalton): Fix size issues!! - assert!(data.len() >= size.x() as usize * size.y() as usize * 4); + fn upload_to_texture(&self, texture: &Self::Texture, rect: RectI, data: TextureDataRef) { + let data_ptr = data.check_and_extract_data_ptr(rect.size(), texture.format); + + assert!(rect.size().x() >= 0); + assert!(rect.size().y() >= 0); + assert!(rect.max_x() <= texture.size.x()); + assert!(rect.max_y() <= texture.size.y()); + unsafe { self.bind_texture(texture, 0); - gl::TexImage2D(gl::TEXTURE_2D, - 0, - texture.format.gl_internal_format(), - size.x() as GLsizei, - size.y() as GLsizei, - 0, - texture.format.gl_format(), - texture.format.gl_type(), - data.as_ptr() as *const GLvoid); ck(); + if rect.origin() == Vector2I::default() && rect.size() == texture.size { + gl::TexImage2D(gl::TEXTURE_2D, + 0, + texture.format.gl_internal_format(), + texture.size.x() as GLsizei, + texture.size.y() as GLsizei, + 0, + texture.format.gl_format(), + texture.format.gl_type(), + data_ptr); ck(); + } else { + gl::TexSubImage2D(gl::TEXTURE_2D, + 0, + rect.origin().x(), + rect.origin().y(), + rect.size().x() as GLsizei, + rect.size().y() as GLsizei, + texture.format.gl_format(), + texture.format.gl_type(), + data_ptr); ck(); + } } self.set_texture_parameters(texture); @@ -529,8 +529,10 @@ impl Device for GLDevice { flip_y(&mut pixels, size, channels); TextureData::U8(pixels) } - TextureFormat::R16F => { - let mut pixels = vec![0; size.x() as usize * size.y() as usize]; + TextureFormat::R16F | TextureFormat::RGBA16F => { + let channels = format.channels(); + let mut pixels = + vec![f16::default(); size.x() as usize * size.y() as usize * channels]; unsafe { gl::ReadPixels(origin.x(), origin.y(), @@ -540,8 +542,8 @@ impl Device for GLDevice { format.gl_type(), pixels.as_mut_ptr() as *mut GLvoid); ck(); } - flip_y(&mut pixels, size, 1); - TextureData::U16(pixels) + flip_y(&mut pixels, size, channels); + TextureData::F16(pixels) } TextureFormat::RGBA32F => { let channels = format.channels(); @@ -991,6 +993,7 @@ impl TextureFormatExt for TextureFormat { TextureFormat::R8 => gl::R8 as GLint, TextureFormat::R16F => gl::R16F as GLint, TextureFormat::RGBA8 => gl::RGBA as GLint, + TextureFormat::RGBA16F => gl::RGBA16F as GLint, TextureFormat::RGBA32F => gl::RGBA32F as GLint, } } @@ -998,14 +1001,14 @@ impl TextureFormatExt for TextureFormat { fn gl_format(self) -> GLuint { match self { TextureFormat::R8 | TextureFormat::R16F => gl::RED, - TextureFormat::RGBA8 | TextureFormat::RGBA32F => gl::RGBA, + TextureFormat::RGBA8 | TextureFormat::RGBA16F | TextureFormat::RGBA32F => gl::RGBA, } } fn gl_type(self) -> GLuint { match self { TextureFormat::R8 | TextureFormat::RGBA8 => gl::UNSIGNED_BYTE, - TextureFormat::R16F => gl::HALF_FLOAT, + TextureFormat::R16F | TextureFormat::RGBA16F => gl::HALF_FLOAT, TextureFormat::RGBA32F => gl::FLOAT, } } diff --git a/gpu/Cargo.toml b/gpu/Cargo.toml index cc9ca12f..58b1e7f1 100644 --- a/gpu/Cargo.toml +++ b/gpu/Cargo.toml @@ -5,6 +5,7 @@ authors = ["Patrick Walton "] edition = "2018" [dependencies] +half = "1.4" [dependencies.image] version = "0.21" diff --git a/gpu/src/lib.rs b/gpu/src/lib.rs index f2bf934f..b791c07c 100644 --- a/gpu/src/lib.rs +++ b/gpu/src/lib.rs @@ -11,12 +11,14 @@ //! Minimal abstractions over GPU device capabilities. use crate::resources::ResourceLoader; +use half::f16; use image::ImageFormat; use pathfinder_content::color::ColorF; use pathfinder_geometry::rect::RectI; use pathfinder_geometry::transform3d::Transform4F; use pathfinder_geometry::vector::Vector2I; use pathfinder_simd::default::{F32x2, F32x4}; +use std::os::raw::c_void; use std::time::Duration; pub mod resources; @@ -68,7 +70,7 @@ pub trait Device: Sized { ); fn framebuffer_texture<'f>(&self, framebuffer: &'f Self::Framebuffer) -> &'f Self::Texture; fn texture_size(&self, texture: &Self::Texture) -> Vector2I; - fn upload_to_texture(&self, texture: &Self::Texture, size: Vector2I, data: &[u8]); + fn upload_to_texture(&self, texture: &Self::Texture, rect: RectI, data: TextureDataRef); fn read_pixels(&self, target: &RenderTarget, viewport: RectI) -> TextureData; fn begin_commands(&self); fn end_commands(&self); @@ -115,6 +117,7 @@ pub enum TextureFormat { R8, R16F, RGBA8, + RGBA16F, RGBA32F, } @@ -304,12 +307,14 @@ impl Default for StencilFunc { pub enum TextureData { U8(Vec), U16(Vec), + F16(Vec), F32(Vec), } #[derive(Clone, Copy, Debug)] pub enum TextureDataRef<'a> { U8(&'a [u8]), + F16(&'a [f16]), F32(&'a [f32]), } @@ -343,7 +348,18 @@ impl TextureFormat { pub fn channels(self) -> usize { match self { TextureFormat::R8 | TextureFormat::R16F => 1, - TextureFormat::RGBA8 | TextureFormat::RGBA32F => 4, + TextureFormat::RGBA8 | TextureFormat::RGBA16F | TextureFormat::RGBA32F => 4, + } + } + + #[inline] + pub fn bytes_per_pixel(self) -> usize { + match self { + TextureFormat::R8 => 1, + TextureFormat::R16F => 2, + TextureFormat::RGBA8 => 4, + TextureFormat::RGBA16F => 8, + TextureFormat::RGBA32F => 16, } } } @@ -354,3 +370,34 @@ impl ClearOps { self.color.is_some() || self.depth.is_some() || self.stencil.is_some() } } + +impl<'a> TextureDataRef<'a> { + #[doc(hidden)] + pub fn check_and_extract_data_ptr(self, minimum_size: Vector2I, format: TextureFormat) + -> *const c_void { + let channels = match (format, self) { + (TextureFormat::R8, TextureDataRef::U8(_)) => 1, + (TextureFormat::RGBA8, TextureDataRef::U8(_)) => 4, + (TextureFormat::RGBA16F, TextureDataRef::F16(_)) => 4, + (TextureFormat::RGBA32F, TextureDataRef::F32(_)) => 4, + _ => panic!("Unimplemented texture format!"), + }; + + let area = minimum_size.x() as usize * minimum_size.y() as usize; + + match self { + TextureDataRef::U8(data) => { + assert!(data.len() >= area * channels); + data.as_ptr() as *const c_void + } + TextureDataRef::F16(data) => { + assert!(data.len() >= area * channels); + data.as_ptr() as *const c_void + } + TextureDataRef::F32(data) => { + assert!(data.len() >= area * channels); + data.as_ptr() as *const c_void + } + } + } +} diff --git a/metal/Cargo.toml b/metal/Cargo.toml index afc77d15..99b01143 100644 --- a/metal/Cargo.toml +++ b/metal/Cargo.toml @@ -11,6 +11,7 @@ block = "0.1" cocoa = "0.19" core-foundation = "0.6" foreign-types = "0.3" +half = "1.4" metal = "0.17" objc = "0.2" diff --git a/metal/src/lib.rs b/metal/src/lib.rs index 12b55773..6124bcbd 100644 --- a/metal/src/lib.rs +++ b/metal/src/lib.rs @@ -23,6 +23,7 @@ use cocoa::foundation::{NSRange, NSUInteger}; use core_foundation::base::TCFType; use core_foundation::string::{CFString, CFStringRef}; use foreign_types::{ForeignType, ForeignTypeRef}; +use half::f16; use metal::{self, Argument, ArgumentEncoder, Buffer, CommandBuffer, CommandBufferRef}; use metal::{CommandQueue, CompileOptions, CoreAnimationDrawable, CoreAnimationDrawableRef}; use metal::{CoreAnimationLayer, CoreAnimationLayerRef, DepthStencilDescriptor, Function, Library}; @@ -196,6 +197,7 @@ impl Device for MetalDevice { TextureFormat::R8 => descriptor.set_pixel_format(MTLPixelFormat::R8Unorm), TextureFormat::R16F => descriptor.set_pixel_format(MTLPixelFormat::R16Float), TextureFormat::RGBA8 => descriptor.set_pixel_format(MTLPixelFormat::RGBA8Unorm), + TextureFormat::RGBA16F => descriptor.set_pixel_format(MTLPixelFormat::RGBA16Float), TextureFormat::RGBA32F => descriptor.set_pixel_format(MTLPixelFormat::RGBA32Float), } descriptor.set_width(size.x() as u64); @@ -207,16 +209,9 @@ impl Device for MetalDevice { fn create_texture_from_data(&self, format: TextureFormat, size: Vector2I, data: TextureDataRef) -> MetalTexture { - match (format, data) { - (TextureFormat::R8, TextureDataRef::U8(data)) => { - assert!(data.len() >= size.x() as usize * size.y() as usize); - let texture = self.create_texture(TextureFormat::R8, size); - self.upload_to_texture(&texture, size, data); - texture - } - _ => panic!("Unimplemented texture format in `create_texture_from_data`!"), - } - + let texture = self.create_texture(format, size); + self.upload_to_texture(&texture, RectI::new(Vector2I::default(), size), data); + texture } fn create_shader_from_source(&self, _: &str, source: &[u8], _: ShaderKind) -> MetalShader { @@ -421,16 +416,25 @@ impl Device for MetalDevice { Vector2I::new(texture.texture.width() as i32, texture.texture.height() as i32) } - fn upload_to_texture(&self, texture: &MetalTexture, size: Vector2I, data: &[u8]) { - assert!(data.len() >= size.x() as usize * size.y() as usize); - let format = self.texture_format(&texture.texture).expect("Unexpected texture format!"); - assert!(format == TextureFormat::R8 || format == TextureFormat::RGBA8); + fn upload_to_texture(&self, texture: &MetalTexture, rect: RectI, data: TextureDataRef) { + let texture_size = self.texture_size(texture); + assert!(rect.size().x() >= 0); + assert!(rect.size().y() >= 0); + assert!(rect.max_x() <= texture_size.x()); + assert!(rect.max_y() <= texture_size.y()); - let origin = MTLOrigin { x: 0, y: 0, z: 0 }; - let size = MTLSize { width: size.x() as u64, height: size.y() as u64, depth: 1 }; + let format = self.texture_format(&texture.texture).expect("Unexpected texture format!"); + let data_ptr = data.check_and_extract_data_ptr(rect.size(), format); + + let origin = MTLOrigin { x: rect.origin().x() as u64, y: rect.origin().y() as u64, z: 0 }; + let size = MTLSize { + width: rect.size().x() as u64, + height: rect.size().y() as u64, + depth: 1, + }; let region = MTLRegion { origin, size }; - let stride = size.width * format.channels() as u64; - texture.texture.replace_region(region, 0, stride, data.as_ptr() as *const _); + let stride = format.bytes_per_pixel() as u64 * size.width; + texture.texture.replace_region(region, 0, stride, data_ptr); texture.dirty.set(true); } @@ -454,14 +458,15 @@ impl Device for MetalDevice { texture.get_bytes(pixels.as_mut_ptr() as *mut _, metal_region, 0, stride as u64); TextureData::U8(pixels) } - TextureFormat::R16F => { - let stride = size.x() as usize; - let mut pixels = vec![0; stride * size.y() as usize]; + TextureFormat::R16F | TextureFormat::RGBA16F => { + let channels = format.channels(); + let stride = size.x() as usize * channels; + let mut pixels = vec![f16::default(); stride * size.y() as usize]; texture.get_bytes(pixels.as_mut_ptr() as *mut _, metal_region, 0, stride as u64 * 2); - TextureData::U16(pixels) + TextureData::F16(pixels) } TextureFormat::RGBA32F => { let channels = format.channels(); diff --git a/renderer/src/gpu/renderer.rs b/renderer/src/gpu/renderer.rs index 545c5118..2d4a0513 100644 --- a/renderer/src/gpu/renderer.rs +++ b/renderer/src/gpu/renderer.rs @@ -21,8 +21,8 @@ use pathfinder_content::color::ColorF; use pathfinder_gpu::resources::ResourceLoader; use pathfinder_gpu::{BlendFunc, BlendState, BufferData, BufferTarget, BufferUploadMode, ClearOps}; use pathfinder_gpu::{DepthFunc, DepthState, Device, Primitive, RenderOptions, RenderState}; -use pathfinder_gpu::{RenderTarget, StencilFunc, StencilState, TextureFormat, UniformData}; -use pathfinder_gpu::{VertexAttrClass, VertexAttrDescriptor, VertexAttrType}; +use pathfinder_gpu::{RenderTarget, StencilFunc, StencilState, TextureDataRef, TextureFormat}; +use pathfinder_gpu::{UniformData, VertexAttrClass, VertexAttrDescriptor, VertexAttrType}; use pathfinder_simd::default::{F32x2, F32x4}; use std::cmp; use std::collections::VecDeque; @@ -378,8 +378,8 @@ where } self.device.upload_to_texture(self.paint_texture.as_ref().unwrap(), - paint_data.size, - &paint_data.texels); + RectI::new(Vector2I::default(), paint_data.size), + TextureDataRef::U8(&paint_data.texels)); } fn upload_solid_tiles(&mut self, solid_tiles: &[SolidTileBatchPrimitive]) {