From 42289eec6ea9e8a50cb76babf4027ed4d318c48c Mon Sep 17 00:00:00 2001 From: Patrick Walton Date: Mon, 29 Jun 2020 12:48:49 -0700 Subject: [PATCH] Fix Metal memory management and the `canvas_metal_minimal`, `canvas_nanovg`, and `macos_app` examples. `winit` does not create an autorelease pool, so the Metal backend had not taken the presence of one into account. Now the Metal backend creates and flushes autorelease pools as necessary. Closes #334. Closes #376. --- Cargo.lock | 42 +++++- c/Cargo.toml | 4 +- c/cbindgen.toml | 4 + c/src/lib.rs | 45 ++++-- demo/common/Cargo.toml | 2 +- demo/native/Cargo.toml | 2 +- demo/native/src/main.rs | 6 +- examples/canvas_metal_minimal/Cargo.toml | 2 +- examples/canvas_metal_minimal/src/main.rs | 8 +- examples/canvas_nanovg/src/main.rs | 10 +- .../project.pbxproj | 12 +- .../xcschemes/Pathfinder Example.xcscheme | 11 +- .../xcdebugger/Breakpoints_v2.xcbkptlist | 2 + .../Pathfinder Example/PathfinderView.h | 4 +- .../Pathfinder Example/PathfinderView.m | 96 ++++--------- metal/Cargo.toml | 2 +- metal/src/lib.rs | 132 +++++++++++++----- renderer/src/gpu/d3d11/renderer.rs | 26 ++-- renderer/src/gpu/d3d9/renderer.rs | 7 +- renderer/src/gpu/renderer.rs | 2 + resources/shaders/gl4/d3d11/tile.cs.glsl | 6 +- resources/shaders/metal/d3d11/tile.cs.metal | 4 +- shaders/d3d11/tile.cs.glsl | 6 +- 23 files changed, 267 insertions(+), 168 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index b5f4cea9..c38b439a 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -224,7 +224,7 @@ version = "0.1.0" dependencies = [ "foreign-types 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)", "gl 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)", + "metal 0.18.0 (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.5.0", "pathfinder_color 0.5.0", @@ -419,6 +419,20 @@ dependencies = [ "objc 0.2.7 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "cocoa" +version = "0.20.2" +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)", + "core-foundation 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)", + "core-graphics 0.19.0 (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.69 (registry+https://github.com/rust-lang/crates.io-index)", + "objc 0.2.7 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "color-backtrace" version = "0.3.0" @@ -658,7 +672,7 @@ dependencies = [ "io-surface 0.12.1 (registry+https://github.com/rust-lang/crates.io-index)", "jemallocator 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)", "lazy_static 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)", + "metal 0.18.0 (registry+https://github.com/rust-lang/crates.io-index)", "nfd 0.0.4 (registry+https://github.com/rust-lang/crates.io-index)", "objc 0.2.7 (registry+https://github.com/rust-lang/crates.io-index)", "pathfinder_demo 0.1.0", @@ -1428,6 +1442,20 @@ dependencies = [ "objc 0.2.7 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "metal" +version = "0.18.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.20.2 (registry+https://github.com/rust-lang/crates.io-index)", + "core-graphics 0.19.0 (registry+https://github.com/rust-lang/crates.io-index)", + "foreign-types 0.3.2 (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)", +] + [[package]] name = "miniz_oxide" version = "0.3.6" @@ -1683,11 +1711,13 @@ name = "pathfinder_c" version = "0.1.0" dependencies = [ "cbindgen 0.13.2 (registry+https://github.com/rust-lang/crates.io-index)", + "core-foundation 0.6.4 (registry+https://github.com/rust-lang/crates.io-index)", "font-kit 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)", "foreign-types 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)", "gl 0.14.0 (registry+https://github.com/rust-lang/crates.io-index)", + "io-surface 0.12.1 (registry+https://github.com/rust-lang/crates.io-index)", "libc 0.2.69 (registry+https://github.com/rust-lang/crates.io-index)", - "metal 0.17.1 (registry+https://github.com/rust-lang/crates.io-index)", + "metal 0.18.0 (registry+https://github.com/rust-lang/crates.io-index)", "pathfinder_canvas 0.5.0", "pathfinder_color 0.5.0", "pathfinder_content 0.5.0", @@ -1746,7 +1776,7 @@ dependencies = [ "image 0.23.3 (registry+https://github.com/rust-lang/crates.io-index)", "io-surface 0.12.1 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", - "metal 0.17.1 (registry+https://github.com/rust-lang/crates.io-index)", + "metal 0.18.0 (registry+https://github.com/rust-lang/crates.io-index)", "pathfinder_color 0.5.0", "pathfinder_content 0.5.0", "pathfinder_export 0.1.0", @@ -1856,7 +1886,7 @@ dependencies = [ "half 1.5.0 (registry+https://github.com/rust-lang/crates.io-index)", "io-surface 0.12.1 (registry+https://github.com/rust-lang/crates.io-index)", "libc 0.2.69 (registry+https://github.com/rust-lang/crates.io-index)", - "metal 0.17.1 (registry+https://github.com/rust-lang/crates.io-index)", + "metal 0.18.0 (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.5.1", "pathfinder_gpu 0.5.0", @@ -3096,6 +3126,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" "checksum cmake 0.1.42 (registry+https://github.com/rust-lang/crates.io-index)" = "81fb25b677f8bf1eb325017cb6bb8452f87969db0fedb4f757b297bee78a7c62" "checksum cocoa 0.18.5 (registry+https://github.com/rust-lang/crates.io-index)" = "1706996401131526e36b3b49f0c4d912639ce110996f3ca144d78946727bce54" "checksum cocoa 0.19.1 (registry+https://github.com/rust-lang/crates.io-index)" = "f29f7768b2d1be17b96158e3285951d366b40211320fb30826a76cb7a0da6400" +"checksum cocoa 0.20.2 (registry+https://github.com/rust-lang/crates.io-index)" = "0c49e86fc36d5704151f5996b7b3795385f50ce09e3be0f47a0cfde869681cf8" "checksum color-backtrace 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "65d13f1078cc63c791d0deba0dd43db37c9ec02b311f10bed10b577016f3a957" "checksum color_quant 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)" = "0dbbb57365263e881e805dc77d94697c9118fd94d8da011240555aa7b23445bd" "checksum combine 3.8.1 (registry+https://github.com/rust-lang/crates.io-index)" = "da3da6baa321ec19e1cc41d31bf599f00c783d0517095cdaf0332e3fe8d20680" @@ -3207,6 +3238,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" "checksum memmap2 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "d9b70ca2a6103ac8b665dc150b142ef0e4e89df640c9e6cf295d189c3caebe5a" "checksum memoffset 0.5.4 (registry+https://github.com/rust-lang/crates.io-index)" = "b4fc2c02a7e374099d4ee95a193111f72d2110197fe200272371758f6c3643d8" "checksum metal 0.17.1 (registry+https://github.com/rust-lang/crates.io-index)" = "f83c7dcc2038e12f68493fa3de44235df27b2497178e257185b4b5b5d028a1e4" +"checksum metal 0.18.0 (registry+https://github.com/rust-lang/crates.io-index)" = "e198a0ee42bdbe9ef2c09d0b9426f3b2b47d90d93a4a9b0395c4cea605e92dc0" "checksum miniz_oxide 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)" = "aa679ff6578b1cddee93d7e82e263b94a575e0bfced07284eb0c037c1d2416a5" "checksum mio 0.6.21 (registry+https://github.com/rust-lang/crates.io-index)" = "302dec22bcf6bae6dfb69c647187f4b4d0fb6f535521f7bc022430ce8e12008f" "checksum mio-extras 2.0.6 (registry+https://github.com/rust-lang/crates.io-index)" = "52403fe290012ce777c4626790c8951324a2b9e3316b3143779c72b029742f19" diff --git a/c/Cargo.toml b/c/Cargo.toml index 2d3353e6..46d898b5 100644 --- a/c/Cargo.toml +++ b/c/Cargo.toml @@ -46,7 +46,9 @@ path = "../simd" path = "../svg" [target.'cfg(target_os = "macos")'.dependencies] -metal = "0.17" +core-foundation = "0.6" +io-surface = "0.12" +metal = "0.18" [target.'cfg(target_os = "macos")'.dependencies.pathfinder_metal] path = "../metal" diff --git a/c/cbindgen.toml b/c/cbindgen.toml index f8af9071..902ee9b5 100644 --- a/c/cbindgen.toml +++ b/c/cbindgen.toml @@ -35,18 +35,21 @@ include = [ "pathfinder_gpu", "pathfinder_metal", "pathfinder_renderer", + "pathfinder_svg", ] [export.rename] "BuildOptions" = "PFBuildOptionsPrivate" "CanvasFontContext" = "PFCanvasFontContextPrivate" "CanvasRenderingContext2D" = "PFCanvasRenderingContext2DPrivate" +"CoreAnimationDrawableRef" = "NSObject" "DestFramebuffer_GLDevice" = "PFDestFramebufferGLDevicePrivate" "DestFramebuffer_MetalDevice" = "PFDestFramebufferMetalDevicePrivate" "FillStyle" = "PFFillStylePrivate" "GLDevice" = "PFGLDevicePrivate" "Handle" = "FKHandlePrivate" "MetalDevice" = "PFMetalDevicePrivate" +"NativeMetalDeviceRef" = "NSObject" "Path2D" = "PFPath2DPrivate" "RenderTransform" = "PFRenderTransformPrivate" "Renderer_GLDevice" = "PFRendererGLDevicePrivate" @@ -54,3 +57,4 @@ include = [ "ResourceLoaderWrapper" = "PFResourceLoaderWrapperPrivate" "Scene" = "PFScenePrivate" "SceneProxy" = "PFSceneProxyPrivate" +"SVGScene" = "PFSVGScenePrivate" diff --git a/c/src/lib.rs b/c/src/lib.rs index 12d9568b..a20a663f 100644 --- a/c/src/lib.rs +++ b/c/src/lib.rs @@ -44,11 +44,11 @@ use std::str; use usvg::{Options, Tree}; #[cfg(all(target_os = "macos", not(feature = "pf-gl")))] -use metal::{self, CAMetalLayer, CoreAnimationLayerRef}; +use io_surface::IOSurfaceRef; +#[cfg(all(target_os = "macos", not(feature = "pf-gl")))] +use metal::{self, CoreAnimationDrawableRef, DeviceRef as NativeMetalDeviceRef}; #[cfg(all(target_os = "macos", not(feature = "pf-gl")))] use pathfinder_metal::MetalDevice; -#[cfg(all(target_os = "macos", not(feature = "pf-gl")))] -use foreign_types::ForeignTypeRef; // Constants @@ -660,12 +660,39 @@ pub unsafe extern "C" fn PFSceneProxyBuildAndRenderMetal(scene_proxy: PFScenePro #[cfg(all(target_os = "macos", not(feature = "pf-gl")))] #[no_mangle] -pub unsafe extern "C" fn PFMetalDeviceCreate(layer: *mut CAMetalLayer) - -> PFMetalDeviceRef { - let device = - metal::Device::system_default().expect("Failed to get Metal system default device!"); - let layer = CoreAnimationLayerRef::from_ptr(layer); - Box::into_raw(Box::new(MetalDevice::new(device, layer.next_drawable().unwrap()))) +pub unsafe extern "C" fn PFMetalDeviceCreateWithIOSurface(metal_device: &NativeMetalDeviceRef, + io_surface: IOSurfaceRef) + -> PFMetalDeviceRef { + Box::into_raw(Box::new(MetalDevice::new(metal_device, io_surface))) +} + +#[cfg(all(target_os = "macos", not(feature = "pf-gl")))] +#[no_mangle] +pub unsafe extern "C" fn PFMetalDeviceCreateWithDrawable(metal_device: &NativeMetalDeviceRef, + ca_drawable: &CoreAnimationDrawableRef) + -> PFMetalDeviceRef { + Box::into_raw(Box::new(MetalDevice::new(metal_device, ca_drawable))) +} + +#[cfg(all(target_os = "macos", not(feature = "pf-gl")))] +#[no_mangle] +pub unsafe extern "C" fn PFMetalDeviceSwapIOSurface(device: PFMetalDeviceRef, + new_io_surface: IOSurfaceRef) { + drop((*device).swap_texture(new_io_surface)) +} + +#[cfg(all(target_os = "macos", not(feature = "pf-gl")))] +#[no_mangle] +pub unsafe extern "C" fn PFMetalDeviceSwapDrawable(device: PFMetalDeviceRef, + new_ca_drawable: &CoreAnimationDrawableRef) { + drop((*device).swap_texture(new_ca_drawable)) +} + +#[cfg(all(target_os = "macos", not(feature = "pf-gl")))] +#[no_mangle] +pub unsafe extern "C" fn PFMetalDevicePresentDrawable(device: PFMetalDeviceRef, + ca_drawable: &CoreAnimationDrawableRef) { + (*device).present_drawable(ca_drawable) } #[cfg(all(target_os = "macos", not(feature = "pf-gl")))] diff --git a/demo/common/Cargo.toml b/demo/common/Cargo.toml index 169fd9df..2edb17cd 100644 --- a/demo/common/Cargo.toml +++ b/demo/common/Cargo.toml @@ -55,7 +55,7 @@ path = "../../svg" path = "../../ui" [target.'cfg(target_os = "macos")'.dependencies] -metal = "0.17" +metal = "0.18" [target.'cfg(target_os = "macos")'.dependencies.io-surface] version = "0.12" diff --git a/demo/native/Cargo.toml b/demo/native/Cargo.toml index 9c698082..c319d699 100644 --- a/demo/native/Cargo.toml +++ b/demo/native/Cargo.toml @@ -48,7 +48,7 @@ version = "<0.19.4" # 0.19.4 causes build errors https://github.com/rust-windowi [target.'cfg(target_os = "macos")'.dependencies] foreign-types = "0.3" io-surface = "0.12" -metal = "0.17" +metal = "0.18" objc = "0.2" [target.'cfg(target_os = "macos")'.dependencies.pathfinder_metal] diff --git a/demo/native/src/main.rs b/demo/native/src/main.rs index 872a76a2..d869b78e 100644 --- a/demo/native/src/main.rs +++ b/demo/native/src/main.rs @@ -26,6 +26,7 @@ use pathfinder_resources::ResourceLoader; use pathfinder_resources::fs::FilesystemResourceLoader; use std::cell::Cell; use std::collections::VecDeque; +use std::mem; use std::path::PathBuf; use std::sync::Mutex; use surfman::{SurfaceAccess, SurfaceType, declare_surfman}; @@ -160,7 +161,10 @@ impl Window for WindowImpl { #[cfg(all(target_os = "macos", not(feature = "pf-gl")))] fn metal_device(&self) -> metal::Device { - self.metal_device.0.clone() + // FIXME(pcwalton): Remove once `surfman` upgrades `metal-rs` version. + unsafe { + mem::transmute(self.metal_device.0.clone()) + } } #[cfg(all(target_os = "macos", not(feature = "pf-gl")))] diff --git a/examples/canvas_metal_minimal/Cargo.toml b/examples/canvas_metal_minimal/Cargo.toml index 79fd2fb5..5ceab2ed 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.14" -metal = "0.17" +metal = "0.18" objc = "0.2" sdl2 = "0.33" sdl2-sys = "0.33" diff --git a/examples/canvas_metal_minimal/src/main.rs b/examples/canvas_metal_minimal/src/main.rs index 0fa6c208..dd3bb712 100644 --- a/examples/canvas_metal_minimal/src/main.rs +++ b/examples/canvas_metal_minimal/src/main.rs @@ -44,9 +44,13 @@ fn main() { let metal_layer = unsafe { CoreAnimationLayerRef::from_ptr(SDL_RenderGetMetalLayer(canvas.raw()) as *mut CAMetalLayer) }; + let metal_device = metal_layer.device(); + let drawable = metal_layer.next_drawable().unwrap(); // Create a Pathfinder renderer. - let device = MetalDevice::new(metal_layer); + let device = unsafe { + MetalDevice::new(metal_device, drawable.clone()) + }; let mode = RendererMode::default_for_device(&device); let options = RendererOptions { dest: DestFramebuffer::full_window(window_size), @@ -81,7 +85,7 @@ fn main() { renderer.mode().level, RayonExecutor); scene.build_and_render(&mut renderer, BuildOptions::default()); - renderer.device().present_drawable(); + renderer.device().present_drawable(drawable); // Wait for a keypress. let mut event_pump = sdl_context.event_pump().unwrap(); diff --git a/examples/canvas_nanovg/src/main.rs b/examples/canvas_nanovg/src/main.rs index 60620972..dc3a12a3 100644 --- a/examples/canvas_nanovg/src/main.rs +++ b/examples/canvas_nanovg/src/main.rs @@ -30,7 +30,7 @@ use pathfinder_geometry::vector::{Vector2F, vec2f, vec2i}; use pathfinder_gl::{GLDevice, GLVersion}; use pathfinder_renderer::concurrent::rayon::RayonExecutor; use pathfinder_renderer::concurrent::scene_proxy::SceneProxy; -use pathfinder_renderer::gpu::options::{DestFramebuffer, RendererOptions}; +use pathfinder_renderer::gpu::options::{DestFramebuffer, RendererMode, RendererOptions}; use pathfinder_renderer::gpu::renderer::Renderer; use pathfinder_renderer::options::BuildOptions; use pathfinder_resources::ResourceLoader; @@ -1517,13 +1517,15 @@ fn main() { let pathfinder_device = GLDevice::new(GLVersion::GL3, default_framebuffer); // Create a Pathfinder renderer. + let renderer_mode = RendererMode::default_for_device(&pathfinder_device); let renderer_options = RendererOptions { background_color: Some(rgbf(0.3, 0.3, 0.32)), - ..RendererOptions::default_for_device(&pathfinder_device) + dest: DestFramebuffer::full_window(framebuffer_size), + ..RendererOptions::default() }; let mut renderer = Renderer::new(pathfinder_device, &resources, - DestFramebuffer::full_window(framebuffer_size), + renderer_mode, renderer_options); // Initialize font state. @@ -1568,7 +1570,7 @@ fn main() { // Render the canvas to screen. let canvas = context.into_canvas(); let mut scene = SceneProxy::from_scene(canvas.into_scene(), - renderer.level(), + renderer.mode().level, RayonExecutor); scene.build_and_render(&mut renderer, BuildOptions::default()); diff --git a/examples/macos_app/Pathfinder Example.xcodeproj/project.pbxproj b/examples/macos_app/Pathfinder Example.xcodeproj/project.pbxproj index 9a359ecf..3789eff5 100644 --- a/examples/macos_app/Pathfinder Example.xcodeproj/project.pbxproj +++ b/examples/macos_app/Pathfinder Example.xcodeproj/project.pbxproj @@ -7,7 +7,7 @@ objects = { /* Begin PBXBuildFile section */ - 6A9A35B322C1E14700B86652 /* libpathfinder_c.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 6A9A35B222C1E14700B86652 /* libpathfinder_c.a */; }; + 6A7C3B7224A6B75500027B8E /* libpathfinder_c.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 6A7C3B7124A6B75500027B8E /* libpathfinder_c.a */; }; 6AFD6FFA22BD780D00AC1ED3 /* AppDelegate.m in Sources */ = {isa = PBXBuildFile; fileRef = 6AFD6FF922BD780D00AC1ED3 /* AppDelegate.m */; }; 6AFD6FFC22BD781000AC1ED3 /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 6AFD6FFB22BD781000AC1ED3 /* Assets.xcassets */; }; 6AFD6FFF22BD781000AC1ED3 /* MainMenu.xib in Resources */ = {isa = PBXBuildFile; fileRef = 6AFD6FFD22BD781000AC1ED3 /* MainMenu.xib */; }; @@ -17,7 +17,7 @@ /* End PBXBuildFile section */ /* Begin PBXFileReference section */ - 6A9A35B222C1E14700B86652 /* libpathfinder_c.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; name = libpathfinder_c.a; path = ../../../target/release/libpathfinder_c.a; sourceTree = ""; }; + 6A7C3B7124A6B75500027B8E /* libpathfinder_c.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; name = libpathfinder_c.a; path = ../../../target/release/libpathfinder_c.a; sourceTree = ""; }; 6AFD6FF522BD780D00AC1ED3 /* Pathfinder Example.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = "Pathfinder Example.app"; sourceTree = BUILT_PRODUCTS_DIR; }; 6AFD6FF822BD780D00AC1ED3 /* AppDelegate.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = AppDelegate.h; sourceTree = ""; }; 6AFD6FF922BD780D00AC1ED3 /* AppDelegate.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = AppDelegate.m; sourceTree = ""; }; @@ -36,7 +36,7 @@ isa = PBXFrameworksBuildPhase; buildActionMask = 2147483647; files = ( - 6A9A35B322C1E14700B86652 /* libpathfinder_c.a in Frameworks */, + 6A7C3B7224A6B75500027B8E /* libpathfinder_c.a in Frameworks */, 6AFD700F22BD930500AC1ED3 /* libharfbuzz.a in Frameworks */, ); runOnlyForDeploymentPostprocessing = 0; @@ -72,7 +72,7 @@ 6AFD700A22BD7B7A00AC1ED3 /* PathfinderView.m */, 6AFD700122BD781000AC1ED3 /* main.m */, 6AFD700322BD781000AC1ED3 /* Pathfinder_Example.entitlements */, - 6A9A35B222C1E14700B86652 /* libpathfinder_c.a */, + 6A7C3B7124A6B75500027B8E /* libpathfinder_c.a */, 6AFD700E22BD930500AC1ED3 /* libharfbuzz.a */, ); path = "Pathfinder Example"; @@ -290,7 +290,7 @@ CODE_SIGN_STYLE = Automatic; COMBINE_HIDPI_IMAGES = YES; FRAMEWORK_SEARCH_PATHS = ""; - HEADER_SEARCH_PATHS = ../../c/build/include; + HEADER_SEARCH_PATHS = ../../target/release; INFOPLIST_FILE = "Pathfinder Example/Info.plist"; LD_RUNPATH_SEARCH_PATHS = ( "$(inherited)", @@ -312,7 +312,7 @@ CODE_SIGN_STYLE = Automatic; COMBINE_HIDPI_IMAGES = YES; FRAMEWORK_SEARCH_PATHS = ""; - HEADER_SEARCH_PATHS = ../../c/build/include; + HEADER_SEARCH_PATHS = ../../target/release; INFOPLIST_FILE = "Pathfinder Example/Info.plist"; LD_RUNPATH_SEARCH_PATHS = ( "$(inherited)", diff --git a/examples/macos_app/Pathfinder Example.xcodeproj/xcshareddata/xcschemes/Pathfinder Example.xcscheme b/examples/macos_app/Pathfinder Example.xcodeproj/xcshareddata/xcschemes/Pathfinder Example.xcscheme index 06c13d8b..18b88a0d 100644 --- a/examples/macos_app/Pathfinder Example.xcodeproj/xcshareddata/xcschemes/Pathfinder Example.xcscheme +++ b/examples/macos_app/Pathfinder Example.xcodeproj/xcshareddata/xcschemes/Pathfinder Example.xcscheme @@ -27,8 +27,6 @@ selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB" selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB" shouldUseLaunchSchemeArgsEnv = "YES"> - - - - + + - - #import -#include +#include NS_ASSUME_NONNULL_BEGIN @@ -19,8 +19,10 @@ NS_ASSUME_NONNULL_BEGIN PFBuildOptionsRef mBuildOptions; CVDisplayLinkRef mDisplayLink; int32_t mFrameNumber; + CAMetalLayer *mLayer; CGSize mLayerSize; NSLock *mRenderLock; + id mCurrentDrawable; } - (void)_render; diff --git a/examples/macos_app/Pathfinder Example/PathfinderView.m b/examples/macos_app/Pathfinder Example/PathfinderView.m index 03e539d3..bb49d82d 100644 --- a/examples/macos_app/Pathfinder Example/PathfinderView.m +++ b/examples/macos_app/Pathfinder Example/PathfinderView.m @@ -21,45 +21,6 @@ static CVReturn outputCallback(CVDisplayLinkRef displayLink, return kCVReturnSuccess; } -static CATransform3D createPerspectiveMatrix(CGFloat fovY, - CGFloat aspect, - CGFloat zNear, - CGFloat zFar) { - CGFloat f = tan(1.0 / (fovY * 0.5)); - CGFloat zDenom = 1.0 / (zNear - zFar); - - CATransform3D transform = CATransform3DIdentity; - transform.m11 = f / aspect; - transform.m22 = f; - transform.m33 = (zFar + zNear) * zDenom; - transform.m34 = -1.0; - transform.m43 = 2.0 * zFar * zNear * zDenom; - return transform; -} - -static PFTransform3DF pfTransformFromCATransform(const CATransform3D *transform) { - // Core Animation matrices are in column-major order, while Pathfinder matrices are in - // row-major order (at least in the latter's C API). So transpose here. - PFTransform3DF pfTransform; - pfTransform.m00 = (float)transform->m11; - pfTransform.m01 = (float)transform->m21; - pfTransform.m02 = (float)transform->m31; - pfTransform.m03 = (float)transform->m41; - pfTransform.m10 = (float)transform->m12; - pfTransform.m11 = (float)transform->m22; - pfTransform.m12 = (float)transform->m32; - pfTransform.m13 = (float)transform->m42; - pfTransform.m20 = (float)transform->m13; - pfTransform.m21 = (float)transform->m23; - pfTransform.m22 = (float)transform->m33; - pfTransform.m23 = (float)transform->m43; - pfTransform.m30 = (float)transform->m14; - pfTransform.m31 = (float)transform->m24; - pfTransform.m32 = (float)transform->m34; - pfTransform.m33 = (float)transform->m44; - return pfTransform; -} - @implementation PathfinderView #define FONT_SIZE 256.0f @@ -72,46 +33,38 @@ static PFTransform3DF pfTransformFromCATransform(const CATransform3D *transform) PFCanvasRef canvas = PFCanvasCreate(mFontContext, &(PFVector2F){size.width, size.height}); PFFillStyleRef fillStyle = PFFillStyleCreateColor(&(PFColorU){0, 0, 0, 255}); + float scaleX = cosf((float)mFrameNumber * 0.02); + PFTransform2F textTransform; + textTransform.matrix = (PFMatrix2x2F){scaleX, 0.0, 0.0, 1.0}; + textTransform.vector = (PFVector2F){size.width * 0.5, size.height * 0.5}; + PFCanvasSetTransform(canvas, &textTransform); PFCanvasSetFillStyle(canvas, fillStyle); PFCanvasSetFontSize(canvas, FONT_SIZE); PFCanvasSetTextAlign(canvas, PF_TEXT_ALIGN_CENTER); - PFVector2F textOrigin; - textOrigin.x = 0.0; - textOrigin.y = FONT_SIZE * 0.25; - PFCanvasFillText(canvas, "Pathfinder", 0, &textOrigin); - PFCanvasFillRect(canvas, &(const PFRectF){0.0, 0.0, 1.0, 1.0}); + PFCanvasFillText(canvas, "Pathfinder", 0, &(PFVector2F){0.0, FONT_SIZE * 0.5}); PFFillStyleDestroy(fillStyle); PFSceneRef scene = PFCanvasCreateScene(canvas); - PFSceneProxyRef sceneProxy = PFSceneProxyCreateFromSceneAndRayonExecutor(scene); + PFSceneProxyRef sceneProxy = + PFSceneProxyCreateFromSceneAndRayonExecutor(scene, PF_RENDERER_LEVEL_D3D11); - int32_t frame = mFrameNumber; - int32_t nT = frame % 240; - if (nT > 120) - nT = 240 - nT; - - CATransform3D transform = - CATransform3DMakeTranslation(0.0, 0.0, -8.0 + (CGFloat)nT / 120.0 * 8.0); - transform = CATransform3DRotate(transform, - frame / 120.0 * M_PI * 2.0, - 0.0, - 1.0, - 0.0); - transform = CATransform3DScale(transform, -2.0 / size.width, 2.0 / size.height, 1.0); - CGFloat aspect = size.width / size.height; - transform = CATransform3DConcat(transform, - createPerspectiveMatrix(M_PI * 0.25, aspect, 0.01, 10.0)); - PFPerspective pfPerspective; - pfPerspective.transform = pfTransformFromCATransform(&transform); - pfPerspective.window_size.x = size.width; - pfPerspective.window_size.y = size.height; + PFTransform2F pfTransform; + pfTransform.matrix.m00 = 1.0; + pfTransform.matrix.m01 = 0.0; + pfTransform.matrix.m10 = 0.0; + pfTransform.matrix.m11 = 1.0; + pfTransform.vector.x = 0.0; + pfTransform.vector.y = 0.0; PFBuildOptionsRef buildOptions = PFBuildOptionsCreate(); - PFRenderTransformRef renderTransform = PFRenderTransformCreatePerspective(&pfPerspective); + PFRenderTransformRef renderTransform = PFRenderTransformCreate2D(&pfTransform); PFBuildOptionsSetTransform(buildOptions, renderTransform); PFSceneProxyBuildAndRenderMetal(sceneProxy, mRenderer, buildOptions); - PFMetalDevicePresentDrawable(PFMetalRendererGetDevice(mRenderer)); + PFMetalDeviceRef pfMetalDevice = PFMetalRendererGetDevice(mRenderer); + PFMetalDevicePresentDrawable(pfMetalDevice, mCurrentDrawable); + mCurrentDrawable = [mLayer nextDrawable]; + PFMetalDeviceSwapDrawable(pfMetalDevice, mCurrentDrawable); mFrameNumber++; @@ -138,18 +91,23 @@ static PFTransform3DF pfTransformFromCATransform(const CATransform3D *transform) mRenderLock = [[NSLock alloc] init]; mLayerSize = [self convertSizeToBacking:[layer bounds].size]; + mCurrentDrawable = [layer nextDrawable]; + mLayer = layer; - PFMetalDeviceRef device = PFMetalDeviceCreate(layer); + PFMetalDeviceRef device = PFMetalDeviceCreateWithDrawable(mDevice, mCurrentDrawable); PFResourceLoaderRef resourceLoader = PFFilesystemResourceLoaderLocate(); PFMetalDestFramebufferRef destFramebuffer = PFMetalDestFramebufferCreateFullWindow(&(PFVector2I){mLayerSize.width, mLayerSize.height}); + PFRendererMode rendererMode; + rendererMode.level = PF_RENDERER_LEVEL_D3D11; PFRendererOptions rendererOptions; rendererOptions.background_color = (PFColorF){1.0, 1.0, 1.0, 1.0}; rendererOptions.flags = PF_RENDERER_OPTIONS_FLAGS_HAS_BACKGROUND_COLOR; + rendererOptions.dest = destFramebuffer; mRenderer = PFMetalRendererCreate(device, resourceLoader, - destFramebuffer, + &rendererMode, &rendererOptions); mFontContext = PFCanvasFontContextCreateWithSystemSource(); diff --git a/metal/Cargo.toml b/metal/Cargo.toml index 2ec9c903..0941e276 100644 --- a/metal/Cargo.toml +++ b/metal/Cargo.toml @@ -19,7 +19,7 @@ foreign-types = "0.3" half = "1.5" io-surface = "0.12" libc = "0.2" -metal = "0.17" +metal = "0.18" objc = "0.2" [dependencies.pathfinder_geometry] diff --git a/metal/src/lib.rs b/metal/src/lib.rs index 52e1d09d..1755c2b5 100644 --- a/metal/src/lib.rs +++ b/metal/src/lib.rs @@ -19,7 +19,8 @@ extern crate objc; use block::{Block, ConcreteBlock, RcBlock}; use byteorder::{NativeEndian, WriteBytesExt}; -use cocoa::foundation::NSUInteger; +use cocoa::base::{id, nil}; +use cocoa::foundation::{NSAutoreleasePool, NSUInteger}; use core_foundation::base::TCFType; use core_foundation::string::{CFString, CFStringRef}; use dispatch::ffi::dispatch_queue_t; @@ -31,7 +32,7 @@ use libc::size_t; use metal::{self, Argument, ArgumentEncoder, BlitCommandEncoder, Buffer, CommandBuffer}; use metal::{CommandQueue, CompileOptions, ComputeCommandEncoder, ComputePipelineDescriptor}; use metal::{ComputePipelineState, CoreAnimationDrawable, CoreAnimationDrawableRef}; -use metal::{CoreAnimationLayer, CoreAnimationLayerRef, DepthStencilDescriptor, Function, Library}; +use metal::{CoreAnimationLayer, CoreAnimationLayerRef, DepthStencilDescriptor, Device as NativeMetalDevice, DeviceRef, Function, Library}; use metal::{MTLArgument, MTLArgumentEncoder, MTLArgumentType, MTLBlendFactor, MTLBlendOperation}; use metal::{MTLBlitOption, MTLClearColor, MTLColorWriteMask, MTLCompareFunction, MTLComputePipelineState}; use metal::{MTLDataType, MTLDevice, MTLIndexType, MTLLoadAction, MTLOrigin, MTLPixelFormat}; @@ -69,11 +70,11 @@ use std::time::{Duration, Instant}; const FIRST_VERTEX_BUFFER_INDEX: u64 = 16; pub struct MetalDevice { - device: metal::Device, + device: NativeMetalDevice, main_color_texture: Texture, main_depth_stencil_texture: Texture, command_queue: CommandQueue, - command_buffers: RefCell>, + scopes: RefCell>, samplers: Vec, #[allow(dead_code)] dispatch_queue: Queue, @@ -118,9 +119,16 @@ struct StagingBuffer { event_value: u64, } +struct Scope { + autorelease_pool: id, + command_buffer: CommandBuffer, +} + impl MetalDevice { #[inline] - pub unsafe fn new(device: metal::Device, texture: T) -> MetalDevice where T: IntoTexture { + pub unsafe fn new(device: D, texture: T) -> MetalDevice + where D: IntoMetalDevice, T: IntoTexture { + let device = device.into_metal_device(); let command_queue = device.new_command_queue(); let samplers = (0..16).map(|sampling_flags_value| { @@ -176,7 +184,7 @@ impl MetalDevice { main_color_texture: texture, main_depth_stencil_texture, command_queue, - command_buffers: RefCell::new(vec![]), + scopes: RefCell::new(vec![]), samplers, dispatch_queue, timer_query_shared_event, @@ -198,9 +206,20 @@ impl MetalDevice { } #[inline] - pub fn metal_device(&self) -> metal::Device { + pub fn metal_device(&self) -> NativeMetalDevice { self.device.clone() } + + /// A convenience function to present a Core Animation drawable. + pub fn present_drawable(&self, drawable: &CoreAnimationDrawableRef) { + self.begin_commands(); + { + let scopes = self.scopes.borrow(); + let command_buffer = &scopes.last().unwrap().command_buffer; + command_buffer.present_drawable(drawable); + } + self.end_commands(); + } } pub struct MetalFramebuffer(MetalTexture); @@ -491,10 +510,7 @@ impl Device for MetalDevice { let attribute_index = attr.attribute_index(); - let attr_info = vertex_array.descriptor - .attributes() - .object_at(attribute_index as usize) - .unwrap(); + let attr_info = vertex_array.descriptor.attributes().object_at(attribute_index).unwrap(); let format = match (descriptor.class, descriptor.attr_type, descriptor.size) { (VertexAttrClass::Int, VertexAttrType::I8, 2) => MTLVertexFormat::Char2, (VertexAttrClass::Int, VertexAttrType::I8, 3) => MTLVertexFormat::Char3, @@ -577,7 +593,7 @@ impl Device for MetalDevice { // FIXME(pcwalton): Metal separates out per-buffer info from per-vertex info, while our // GL-like API does not. So we end up setting this state over and over again. Not great. - let layout = vertex_array.descriptor.layouts().object_at(buffer_index as usize).unwrap(); + let layout = vertex_array.descriptor.layouts().object_at(buffer_index).unwrap(); if descriptor.divisor == 0 { layout.set_step_function(MTLVertexStepFunction::PerVertex); layout.set_step_rate(1); @@ -671,8 +687,8 @@ impl Device for MetalDevice { self.next_buffer_upload_event_value.set(staging_buffer.event_value + 1); { - let command_buffers = self.command_buffers.borrow(); - let command_buffer = command_buffers.last().unwrap(); + let scopes = self.scopes.borrow(); + let command_buffer = &scopes.last().unwrap().command_buffer; let blit_command_encoder = command_buffer.real_new_blit_command_encoder(); blit_command_encoder.copy_from_buffer(&staging_buffer.buffer, byte_start, @@ -731,8 +747,10 @@ impl Device for MetalDevice { } fn upload_to_texture(&self, dest_texture: &MetalTexture, rect: RectI, data: TextureDataRef) { - let command_buffers = self.command_buffers.borrow(); - let command_buffer = command_buffers.last().expect("Must call `begin_commands()` first!"); + let scopes = self.scopes.borrow(); + let command_buffer = &scopes.last() + .expect("Must call `begin_commands()` first!") + .command_buffer; let texture_size = self.texture_size(dest_texture); let texture_format = self.texture_format(&dest_texture.private_texture) @@ -817,8 +835,8 @@ impl Device for MetalDevice { -> MetalBufferDataReceiver { let buffer_data_receiver; { - let command_buffers = self.command_buffers.borrow(); - let command_buffer = command_buffers.last().unwrap(); + let scopes = self.scopes.borrow(); + let command_buffer = &scopes.last().unwrap().command_buffer; let mut src_allocations = src_buffer.allocations.borrow_mut(); let src_allocations = &mut *src_allocations; @@ -880,12 +898,19 @@ impl Device for MetalDevice { } fn begin_commands(&self) { - self.command_buffers.borrow_mut().push(self.command_queue.new_command_buffer_retained()) + unsafe { + let autorelease_pool = NSAutoreleasePool::new(nil); + let command_buffer = self.command_queue.new_command_buffer_retained(); + self.scopes.borrow_mut().push(Scope { autorelease_pool, command_buffer }) + } } fn end_commands(&self) { - let command_buffer = self.command_buffers.borrow_mut().pop().unwrap(); - command_buffer.commit(); + let scope = self.scopes.borrow_mut().pop().unwrap(); + scope.command_buffer.commit(); + unsafe { + let () = msg_send![scope.autorelease_pool, release]; + } } fn draw_arrays(&self, index_count: u32, render_state: &RenderState) { @@ -937,8 +962,8 @@ impl Device for MetalDevice { fn dispatch_compute(&self, size: ComputeDimensions, compute_state: &ComputeState) { - let command_buffers = self.command_buffers.borrow(); - let command_buffer = command_buffers.last().unwrap(); + let scopes = self.scopes.borrow(); + let command_buffer = &scopes.last().unwrap().command_buffer; let encoder = command_buffer.real_new_compute_command_encoder(); @@ -1034,10 +1059,11 @@ impl Device for MetalDevice { .notify_listener_at_value(&self.shared_event_listener, start_event_value, (*guard.start_block.as_ref().unwrap()).clone()); - self.command_buffers + self.scopes .borrow_mut() .last() .unwrap() + .command_buffer .encode_signal_event(&self.timer_query_shared_event, start_event_value); } @@ -1047,10 +1073,11 @@ impl Device for MetalDevice { .notify_listener_at_value(&self.shared_event_listener, guard.start_event_value + 1, (*guard.end_block.as_ref().unwrap()).clone()); - self.command_buffers + self.scopes .borrow_mut() .last() .unwrap() + .command_buffer .encode_signal_event(&self.timer_query_shared_event, guard.start_event_value + 1); } @@ -1110,7 +1137,12 @@ impl Device for MetalDevice { *captured_fence.0.mutex.lock().unwrap() = MetalFenceStatus::Resolved; captured_fence.0.cond.notify_all(); }); - self.command_buffers.borrow_mut().last().unwrap().add_completed_handler(block.copy()); + self.scopes + .borrow_mut() + .last() + .unwrap() + .command_buffer + .add_completed_handler(block.copy()); self.end_commands(); self.begin_commands(); fence @@ -1334,8 +1366,8 @@ impl MetalDevice { } fn prepare_to_draw(&self, render_state: &RenderState) -> RenderCommandEncoder { - let command_buffers = self.command_buffers.borrow(); - let command_buffer = command_buffers.last().unwrap(); + let scopes = self.scopes.borrow(); + let command_buffer = &scopes.last().unwrap().command_buffer; let render_pass_descriptor = self.create_render_pass_descriptor(render_state); @@ -1873,8 +1905,8 @@ impl MetalDevice { fn synchronize_texture(&self, texture: &Texture, block: RcBlock<(*mut Object,), ()>) { { - let command_buffers = self.command_buffers.borrow(); - let command_buffer = command_buffers.last().unwrap(); + let scopes = self.scopes.borrow(); + let command_buffer = &scopes.last().unwrap().command_buffer; let encoder = command_buffer.real_new_blit_command_encoder(); encoder.synchronize_resource(&texture); command_buffer.add_completed_handler(block); @@ -1890,7 +1922,7 @@ trait DeviceExtra { fn create_depth_stencil_texture(&self, size: Vector2I) -> Texture; } -impl DeviceExtra for metal::Device { +impl DeviceExtra for NativeMetalDevice { fn create_depth_stencil_texture(&self, size: Vector2I) -> Texture { let descriptor = TextureDescriptor::new(); descriptor.set_texture_type(MTLTextureType::D2); @@ -1919,6 +1951,26 @@ impl MetalTexture { } } +pub trait IntoMetalDevice { + fn into_metal_device(self) -> NativeMetalDevice; +} + +impl IntoMetalDevice for NativeMetalDevice { + #[inline] + fn into_metal_device(self) -> NativeMetalDevice { + self + } +} + +impl<'a> IntoMetalDevice for &'a DeviceRef { + #[inline] + fn into_metal_device(self) -> NativeMetalDevice { + unsafe { + msg_send![self, retain] + } + } +} + pub trait IntoTexture { unsafe fn into_texture(self, metal_device: &metal::Device) -> Texture; } @@ -2388,21 +2440,24 @@ impl CommandBufferExt for CommandBuffer { fn new_render_command_encoder_retained(&self, render_pass_descriptor: &RenderPassDescriptorRef) -> RenderCommandEncoder { unsafe { - RenderCommandEncoder::from_ptr( + let encoder: id = msg_send![self.as_ptr(), - renderCommandEncoderWithDescriptor:render_pass_descriptor.as_ptr()]) + renderCommandEncoderWithDescriptor:render_pass_descriptor.as_ptr()]; + RenderCommandEncoder::from_ptr(msg_send![encoder, retain]) } } fn real_new_blit_command_encoder(&self) -> BlitCommandEncoder { unsafe { - BlitCommandEncoder::from_ptr(msg_send![self.as_ptr(), blitCommandEncoder]) + let encoder: id = msg_send![self.as_ptr(), blitCommandEncoder]; + BlitCommandEncoder::from_ptr(msg_send![encoder, retain]) } } fn real_new_compute_command_encoder(&self) -> ComputeCommandEncoder { unsafe { - ComputeCommandEncoder::from_ptr(msg_send![self.as_ptr(), computeCommandEncoder]) + let encoder: id = msg_send![self.as_ptr(), computeCommandEncoder]; + ComputeCommandEncoder::from_ptr(msg_send![encoder, retain]) } } } @@ -2415,7 +2470,8 @@ trait CommandQueueExt { impl CommandQueueExt for CommandQueue { fn new_command_buffer_retained(&self) -> CommandBuffer { unsafe { - CommandBuffer::from_ptr(msg_send![self.as_ptr(), commandBuffer]) + let command_buffer: id = msg_send![self.as_ptr(), commandBuffer]; + CommandBuffer::from_ptr(msg_send![command_buffer, retain]) } } } @@ -2567,8 +2623,8 @@ trait RenderPassDescriptorExt { impl RenderPassDescriptorExt for RenderPassDescriptor { fn new_retained() -> RenderPassDescriptor { unsafe { - RenderPassDescriptor::from_ptr(msg_send![class!(MTLRenderPassDescriptor), - renderPassDescriptor]) + let descriptor: id = msg_send![class!(MTLRenderPassDescriptor), renderPassDescriptor]; + RenderPassDescriptor::from_ptr(msg_send![descriptor, retain]) } } } diff --git a/renderer/src/gpu/d3d11/renderer.rs b/renderer/src/gpu/d3d11/renderer.rs index 7719e080..9bfa66d9 100644 --- a/renderer/src/gpu/d3d11/renderer.rs +++ b/renderer/src/gpu/d3d11/renderer.rs @@ -586,14 +586,24 @@ impl RendererD3D11 where D: Device { (&propagate_program.alpha_tiles_storage_buffer, alpha_tiles_storage_buffer), ]; - if let Some(clip_buffer_ids) = clip_buffer_ids { - let clip_metadata_buffer_id = - clip_buffer_ids.metadata.expect("Where's the clip metadata storage?"); - let clip_metadata_buffer = core.allocator.get_buffer(clip_metadata_buffer_id); - let clip_tile_buffer = core.allocator.get_buffer(clip_buffer_ids.tiles); - storage_buffers.push((&propagate_program.clip_metadata_storage_buffer, - clip_metadata_buffer)); - storage_buffers.push((&propagate_program.clip_tiles_storage_buffer, clip_tile_buffer)); + match clip_buffer_ids { + Some(clip_buffer_ids) => { + let clip_metadata_buffer_id = + clip_buffer_ids.metadata.expect("Where's the clip metadata storage?"); + let clip_metadata_buffer = core.allocator.get_buffer(clip_metadata_buffer_id); + let clip_tile_buffer = core.allocator.get_buffer(clip_buffer_ids.tiles); + storage_buffers.push((&propagate_program.clip_metadata_storage_buffer, + clip_metadata_buffer)); + storage_buffers.push((&propagate_program.clip_tiles_storage_buffer, + clip_tile_buffer)); + } + None => { + // Just attach any old buffers to these, to satisfy Metal. + storage_buffers.push((&propagate_program.clip_metadata_storage_buffer, + propagate_metadata_storage_buffer)); + storage_buffers.push((&propagate_program.clip_tiles_storage_buffer, + tiles_d3d11_buffer)); + } } let timer_query = core.timer_query_cache.start_timing_draw_call(&core.device, diff --git a/renderer/src/gpu/d3d9/renderer.rs b/renderer/src/gpu/d3d9/renderer.rs index 6f35f6b4..57bf2c36 100644 --- a/renderer/src/gpu/d3d9/renderer.rs +++ b/renderer/src/gpu/d3d9/renderer.rs @@ -425,11 +425,8 @@ impl RendererD3D9 where D: Device { uniforms.push((&tile_raster_program.transform_uniform, UniformData::Mat4(self.tile_transform(core).to_columns()))); - - if needs_readable_framebuffer { - textures.push((&tile_raster_program.dest_texture, - core.device.framebuffer_texture(dest_blend_framebuffer))); - } + textures.push((&tile_raster_program.dest_texture, + core.device.framebuffer_texture(dest_blend_framebuffer))); let z_buffer_texture = core.allocator.get_texture(z_buffer_texture_id); textures.push((&tile_raster_program.common.z_buffer_texture, z_buffer_texture)); diff --git a/renderer/src/gpu/renderer.rs b/renderer/src/gpu/renderer.rs index 84c4536c..2fd72360 100644 --- a/renderer/src/gpu/renderer.rs +++ b/renderer/src/gpu/renderer.rs @@ -1010,6 +1010,8 @@ impl RendererCore where D: Device { UniformData::Vec2(color_texture_size.0))); } None => { + // Attach any old texture, just to satisfy Metal. + textures.push((&tile_program.color_texture_0, texture_metadata_texture)); uniforms.push((&tile_program.color_texture_size_0_uniform, UniformData::Vec2(F32x2::default()))); } diff --git a/resources/shaders/gl4/d3d11/tile.cs.glsl b/resources/shaders/gl4/d3d11/tile.cs.glsl index c7470675..0364fb14 100644 --- a/resources/shaders/gl4/d3d11/tile.cs.glsl +++ b/resources/shaders/gl4/d3d11/tile.cs.glsl @@ -673,7 +673,6 @@ uniform sampler2D uZBuffer; uniform ivec2 uZBufferSize; uniform sampler2D uColorTexture0; uniform sampler2D uMaskTexture0; -uniform sampler2D uDestTexture; uniform sampler2D uGammaLUT; uniform vec2 uColorTextureSize0; uniform vec2 uMaskTextureSize0; @@ -762,10 +761,13 @@ void main(){ filterParams2, ctrl); + + + vec4 srcColor = calculateColor(fragCoord, uColorTexture0, uMaskTexture0, - uDestTexture, + uColorTexture0, uGammaLUT, uColorTextureSize0, uMaskTextureSize0, diff --git a/resources/shaders/metal/d3d11/tile.cs.metal b/resources/shaders/metal/d3d11/tile.cs.metal index 27f98375..0467fba4 100644 --- a/resources/shaders/metal/d3d11/tile.cs.metal +++ b/resources/shaders/metal/d3d11/tile.cs.metal @@ -647,7 +647,7 @@ float4 calculateColor(thread const float2& fragCoord, thread const texture2d uDestImage [[texture(0)]], texture2d uTextureMetadata [[texture(1)]], texture2d uColorTexture0 [[texture(2)]], texture2d uMaskTexture0 [[texture(3)]], texture2d uDestTexture [[texture(4)]], texture2d uGammaLUT [[texture(5)]], sampler uTextureMetadataSmplr [[sampler(0)]], sampler uColorTexture0Smplr [[sampler(1)]], sampler uMaskTexture0Smplr [[sampler(2)]], sampler uDestTextureSmplr [[sampler(3)]], sampler uGammaLUTSmplr [[sampler(4)]], uint3 gl_WorkGroupID [[threadgroup_position_in_grid]], uint3 gl_LocalInvocationID [[thread_position_in_threadgroup]]) +kernel void main0(constant int2& uFramebufferTileSize [[buffer(3)]], constant int& uLoadAction [[buffer(4)]], constant int2& uTextureMetadataSize [[buffer(7)]], constant float2& uFramebufferSize [[buffer(0)]], constant float2& uTileSize [[buffer(1)]], constant float4& uClearColor [[buffer(5)]], constant float2& uColorTextureSize0 [[buffer(8)]], constant float2& uMaskTextureSize0 [[buffer(9)]], const device bFirstTileMap& _1510 [[buffer(2)]], const device bTiles& _1603 [[buffer(6)]], texture2d uDestImage [[texture(0)]], texture2d uTextureMetadata [[texture(1)]], texture2d uColorTexture0 [[texture(2)]], texture2d uMaskTexture0 [[texture(3)]], texture2d uGammaLUT [[texture(4)]], sampler uTextureMetadataSmplr [[sampler(0)]], sampler uColorTexture0Smplr [[sampler(1)]], sampler uMaskTexture0Smplr [[sampler(2)]], sampler uGammaLUTSmplr [[sampler(3)]], uint3 gl_WorkGroupID [[threadgroup_position_in_grid]], uint3 gl_LocalInvocationID [[thread_position_in_threadgroup]]) { int2 tileCoord = int2(gl_WorkGroupID.xy); int2 firstTileSubCoord = int2(gl_LocalInvocationID.xy) * int2(1, 4); @@ -723,7 +723,7 @@ kernel void main0(constant int2& uFramebufferTileSize [[buffer(3)]], constant in float2 param_19 = colorTexCoord0; float4 param_20 = baseColor; int param_21 = tileCtrl; - float4 srcColor = calculateColor(param_10, uColorTexture0, uColorTexture0Smplr, uMaskTexture0, uMaskTexture0Smplr, uDestTexture, uDestTextureSmplr, uGammaLUT, uGammaLUTSmplr, param_11, param_12, param_13, param_14, param_15, param_16, param_17, param_18, param_19, param_20, param_21); + float4 srcColor = calculateColor(param_10, uColorTexture0, uColorTexture0Smplr, uMaskTexture0, uMaskTexture0Smplr, uColorTexture0, uColorTexture0Smplr, uGammaLUT, uGammaLUTSmplr, param_11, param_12, param_13, param_14, param_15, param_16, param_17, param_18, param_19, param_20, param_21); destColors[subY_1] = (destColors[subY_1] * (1.0 - srcColor.w)) + srcColor; } tileIndex = int(_1603.iTiles[(tileIndex * 4) + 0]); diff --git a/shaders/d3d11/tile.cs.glsl b/shaders/d3d11/tile.cs.glsl index da171693..f4400e8c 100644 --- a/shaders/d3d11/tile.cs.glsl +++ b/shaders/d3d11/tile.cs.glsl @@ -40,7 +40,6 @@ uniform sampler2D uZBuffer; uniform ivec2 uZBufferSize; uniform sampler2D uColorTexture0; uniform sampler2D uMaskTexture0; -uniform sampler2D uDestTexture; uniform sampler2D uGammaLUT; uniform vec2 uColorTextureSize0; uniform vec2 uMaskTextureSize0; @@ -129,10 +128,13 @@ void main() { filterParams2, ctrl); + // FIXME(pcwalton): The `uColorTexture0` below is a placeholder and needs to be + // replaced! + vec4 srcColor = calculateColor(fragCoord, uColorTexture0, uMaskTexture0, - uDestTexture, + uColorTexture0, uGammaLUT, uColorTextureSize0, uMaskTextureSize0,