From ac1caecd2d6820bcbdfe7894a995c33c7798ab0d Mon Sep 17 00:00:00 2001 From: Billy Messenger <60663878+BillyDM@users.noreply.github.com> Date: Sat, 14 Dec 2024 17:10:03 -0600 Subject: [PATCH 1/7] add "bring your own gui" example plugins --- Cargo.lock | 453 +++++++++++- Cargo.toml | 3 + plugins/examples/byo_gui_gl/Cargo.toml | 22 + plugins/examples/byo_gui_gl/src/lib.rs | 553 ++++++++++++++ plugins/examples/byo_gui_gl/src/main.rs | 7 + .../examples/byo_gui_softbuffer/Cargo.toml | 23 + .../examples/byo_gui_softbuffer/src/lib.rs | 585 +++++++++++++++ .../examples/byo_gui_softbuffer/src/main.rs | 7 + plugins/examples/byo_gui_wgpu/Cargo.toml | 24 + plugins/examples/byo_gui_wgpu/src/lib.rs | 673 ++++++++++++++++++ plugins/examples/byo_gui_wgpu/src/main.rs | 7 + 11 files changed, 2343 insertions(+), 14 deletions(-) create mode 100644 plugins/examples/byo_gui_gl/Cargo.toml create mode 100644 plugins/examples/byo_gui_gl/src/lib.rs create mode 100644 plugins/examples/byo_gui_gl/src/main.rs create mode 100644 plugins/examples/byo_gui_softbuffer/Cargo.toml create mode 100644 plugins/examples/byo_gui_softbuffer/src/lib.rs create mode 100644 plugins/examples/byo_gui_softbuffer/src/main.rs create mode 100644 plugins/examples/byo_gui_wgpu/Cargo.toml create mode 100644 plugins/examples/byo_gui_wgpu/src/lib.rs create mode 100644 plugins/examples/byo_gui_wgpu/src/main.rs diff --git a/Cargo.lock b/Cargo.lock index 6594fd558..bbe3508bb 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -129,6 +129,12 @@ version = "0.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "250f629c0161ad8107cf89319e990051fae62832fd343083bea452d93e2205fd" +[[package]] +name = "allocator-api2" +version = "0.2.21" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "683d7910e743518b0e34f1186f92494becacb047c7b6bf616c96772180fef923" + [[package]] name = "alsa" version = "0.7.1" @@ -321,6 +327,15 @@ version = "1.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "175571dd1d178ced59193a6fc02dde1b972eb0bc56c892cde9beeceac5bf0f6b" +[[package]] +name = "ash" +version = "0.38.0+1.3.281" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0bb44936d800fea8f016d7f2311c6a4f97aebd5dc86f09906139ec848cf3a46f" +dependencies = [ + "libloading 0.8.5", +] + [[package]] name = "assert_no_alloc" version = "1.1.2" @@ -665,7 +680,7 @@ version = "0.1.0" source = "git+https://github.com/RustAudio/baseview.git?rev=1d9806d5bd92275d0d8142d9c9c90198757b9b25#1d9806d5bd92275d0d8142d9c9c90198757b9b25" dependencies = [ "cocoa", - "core-foundation", + "core-foundation 0.9.4", "keyboard-types", "nix 0.22.3", "objc", @@ -683,7 +698,7 @@ version = "0.1.0" source = "git+https://github.com/RustAudio/baseview.git?rev=2c1b1a7b0fef1a29a5150a6a8f6fef6a0cbab8c4#2c1b1a7b0fef1a29a5150a6a8f6fef6a0cbab8c4" dependencies = [ "cocoa", - "core-foundation", + "core-foundation 0.9.4", "keyboard-types", "nix 0.22.3", "objc", @@ -701,7 +716,7 @@ version = "0.1.0" source = "git+https://github.com/RustAudio/baseview.git?rev=579130ecb4f9f315ae52190af42f0ea46aeaa4a2#579130ecb4f9f315ae52190af42f0ea46aeaa4a2" dependencies = [ "cocoa", - "core-foundation", + "core-foundation 0.9.4", "keyboard-types", "nix 0.22.3", "objc", @@ -718,7 +733,24 @@ version = "0.1.0" source = "git+https://github.com/RustAudio/baseview.git?rev=9a0b42c09d712777b2edb4c5e0cb6baf21e988f0#9a0b42c09d712777b2edb4c5e0cb6baf21e988f0" dependencies = [ "cocoa", - "core-foundation", + "core-foundation 0.9.4", + "keyboard-types", + "nix 0.22.3", + "objc", + "raw-window-handle 0.5.2", + "uuid", + "winapi", + "x11", + "x11rb 0.13.1", +] + +[[package]] +name = "baseview" +version = "0.1.0" +source = "git+https://github.com/RustAudio/baseview.git?rev=9a0b42c09d712777b2edb4c5e0cb6baf21e988f0#9a0b42c09d712777b2edb4c5e0cb6baf21e988f0" +dependencies = [ + "cocoa", + "core-foundation 0.9.4", "keyboard-types", "nix 0.22.3", "objc", @@ -747,6 +779,12 @@ dependencies = [ "syn 2.0.98", ] +[[package]] +name = "bit-vec" +version = "0.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5e764a1d40d510daf35e07be9eb06e75770908c27d411ee6c92109c9840eaaf7" + [[package]] name = "bitflags" version = "1.3.2" @@ -1092,12 +1130,22 @@ checksum = "8c6234cbb2e4c785b456c0644748b1ac416dd045799740356f8363dfe00c93f7" dependencies = [ "bitflags 1.3.2", "block", - "core-foundation", - "core-graphics-types", + "core-foundation 0.9.4", + "core-graphics-types 0.1.3", "libc", "objc", ] +[[package]] +name = "codespan-reporting" +version = "0.11.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3538270d33cc669650c4b093848450d380def10c331d38c768e34cac80576e6e" +dependencies = [ + "termcolor", + "unicode-width", +] + [[package]] name = "color_quant" version = "1.1.0" @@ -1195,6 +1243,16 @@ dependencies = [ "libc", ] +[[package]] +name = "core-foundation" +version = "0.10.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b55271e5c8c478ad3f38ad24ef34923091e0548492a266d19b3c0b4d82574c63" +dependencies = [ + "core-foundation-sys", + "libc", +] + [[package]] name = "core-foundation-sys" version = "0.8.7" @@ -1234,7 +1292,18 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "45390e6114f68f718cc7a830514a96f903cccd70d02a8f6d9f643ac4ba45afaf" dependencies = [ "bitflags 1.3.2", - "core-foundation", + "core-foundation 0.9.4", + "libc", +] + +[[package]] +name = "core-graphics-types" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3d44a101f213f6c4cdc1853d4b78aef6db6bdfa3468798cc1d9912f4735013eb" +dependencies = [ + "bitflags 2.6.0", + "core-foundation 0.10.0", "libc", ] @@ -1276,7 +1345,7 @@ version = "0.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1a7847ca018a67204508b77cb9e6de670125075f7464fff5f673023378fa34f5" dependencies = [ - "core-foundation", + "core-foundation 0.9.4", "core-foundation-sys", "coremidi-sys", ] @@ -1459,6 +1528,12 @@ dependencies = [ "syn 2.0.98", ] +[[package]] +name = "ctor-lite" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1f791803201ab277ace03903de1594460708d2d54df6053f2d9e82f592b19e3b" + [[package]] name = "cty" version = "0.2.2" @@ -2366,11 +2441,11 @@ dependencies = [ "bitflags 1.3.2", "cfg_aliases 0.1.1", "cgl", - "core-foundation", + "core-foundation 0.9.4", "dispatch", "glutin_egl_sys", "glutin_glx_sys", - "glutin_wgl_sys", + "glutin_wgl_sys 0.4.0", "libloading 0.7.4", "objc2 0.3.0-beta.3.patch-leaks.3", "once_cell", @@ -2420,6 +2495,15 @@ dependencies = [ "gl_generator", ] +[[package]] +name = "glutin_wgl_sys" +version = "0.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0a4e1951bbd9434a81aa496fe59ccc2235af3820d27b85f9314e279609211e2c" +dependencies = [ + "gl_generator", +] + [[package]] name = "glyph_brush" version = "0.7.12" @@ -2469,6 +2553,57 @@ dependencies = [ "scroll", ] +[[package]] +name = "gpu-alloc" +version = "0.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fbcd2dba93594b227a1f57ee09b8b9da8892c34d55aa332e034a228d0fe6a171" +dependencies = [ + "bitflags 2.6.0", + "gpu-alloc-types", +] + +[[package]] +name = "gpu-alloc-types" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "98ff03b468aa837d70984d55f5d3f846f6ec31fe34bbb97c4f85219caeee1ca4" +dependencies = [ + "bitflags 2.6.0", +] + +[[package]] +name = "gpu-allocator" +version = "0.27.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c151a2a5ef800297b4e79efa4f4bec035c5f51d5ae587287c9b952bdf734cacd" +dependencies = [ + "log", + "presser", + "thiserror", + "windows 0.58.0", +] + +[[package]] +name = "gpu-descriptor" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9c08c1f623a8d0b722b8b99f821eb0ba672a1618f0d3b16ddbee1cedd2dd8557" +dependencies = [ + "bitflags 2.6.0", + "gpu-descriptor-types", + "hashbrown", +] + +[[package]] +name = "gpu-descriptor-types" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fdf242682df893b86f33a73828fb09ca4b2d3bb6cc95249707fc684d27484b91" +dependencies = [ + "bitflags 2.6.0", +] + [[package]] name = "hashbrown" version = "0.15.2" @@ -2508,6 +2643,12 @@ version = "0.4.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7f24254aa9a54b5c858eaee2f5bccdb46aaf0e486a595ed5fd8f86ba55232a70" +[[package]] +name = "hexf-parse" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dfa686283ad6dd069f105e5ab091b04c62850d3e4cf5d67debad1933f55023df" + [[package]] name = "iana-time-zone" version = "0.1.61" @@ -2811,6 +2952,17 @@ dependencies = [ "bitflags 1.3.2", ] +[[package]] +name = "khronos-egl" +version = "6.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6aae1df220ece3c0ada96b8153459b67eebe9ae9212258bb0134ae60416fdf76" +dependencies = [ + "libc", + "libloading 0.8.5", + "pkg-config", +] + [[package]] name = "khronos_api" version = "3.1.0" @@ -3056,6 +3208,21 @@ dependencies = [ "autocfg", ] +[[package]] +name = "metal" +version = "0.29.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7ecfd3296f8c56b7c1f6fbac3c71cefa9d78ce009850c45000015f206dc7fa21" +dependencies = [ + "bitflags 2.6.0", + "block", + "core-graphics-types 0.1.3", + "foreign-types 0.5.0", + "log", + "objc", + "paste", +] + [[package]] name = "midi-consts" version = "0.1.0" @@ -3122,6 +3289,27 @@ dependencies = [ "smallvec", ] +[[package]] +name = "naga" +version = "23.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3d5941e45a15b53aad4375eedf02033adb7a28931eedc31117faffa52e6a857e" +dependencies = [ + "arrayvec 0.7.6", + "bit-set", + "bitflags 2.6.0", + "cfg_aliases 0.1.1", + "codespan-reporting", + "hexf-parse", + "indexmap", + "log", + "rustc-hash 1.1.0", + "spirv", + "termcolor", + "thiserror", + "unicode-xid", +] + [[package]] name = "ndk" version = "0.7.0" @@ -3228,7 +3416,7 @@ dependencies = [ "cfg-if", "clap", "clap-sys", - "core-foundation", + "core-foundation 0.9.4", "cpal", "crossbeam", "jack", @@ -4145,6 +4333,12 @@ dependencies = [ "windows-sys 0.59.0", ] +[[package]] +name = "pollster" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2f3a9f18d041e6d0e102a0a46750538147e5e8992d3b4873aaafee2520b00ce3" + [[package]] name = "poly_mod_synth" version = "0.1.0" @@ -4175,6 +4369,12 @@ version = "0.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "925383efa346730478fb4838dbe9137d2a47675ad789c546d150a6e1dd4ab31c" +[[package]] +name = "presser" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e8cf8e6a8aa66ce33f63993ffc4ea4271eb5b0530a9002db8455ea6050c77bfa" + [[package]] name = "primal-check" version = "0.3.4" @@ -4349,6 +4549,12 @@ dependencies = [ "rand_core 0.6.4", ] +[[package]] +name = "range-alloc" +version = "0.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9c8a99fddc9f0ba0a85884b8d14e3592853e787d581ca1816c91349b10e4eeab" + [[package]] name = "rangemap" version = "1.5.1" @@ -4937,6 +5143,34 @@ dependencies = [ "nih_plug", ] +[[package]] +name = "softbuffer" +version = "0.4.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "18051cdd562e792cad055119e0cdb2cfc137e44e3987532e0f9659a77931bb08" +dependencies = [ + "as-raw-xcb-connection", + "bytemuck", + "cfg_aliases 0.2.1", + "core-graphics 0.24.0", + "drm", + "fastrand 2.1.0", + "foreign-types 0.5.0", + "js-sys", + "log", + "objc2 0.5.2", + "objc2-foundation", + "objc2-quartz-core", + "raw-window-handle 0.6.2", + "redox_syscall 0.5.3", + "rustix 0.38.34", + "tiny-xlib", + "wasm-bindgen", + "web-sys", + "windows-sys 0.59.0", + "x11rb 0.13.1", +] + [[package]] name = "spectral_compressor" version = "0.4.3" @@ -4951,6 +5185,15 @@ dependencies = [ "triple_buffer", ] +[[package]] +name = "spirv" +version = "0.3.0+sdk-1.3.268.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "eda41003dc44290527a59b13432d4a0379379fa074b70174882adfbdfd917844" +dependencies = [ + "bitflags 2.6.0", +] + [[package]] name = "static_assertions" version = "1.1.0" @@ -5132,6 +5375,18 @@ dependencies = [ "time-core", ] +[[package]] +name = "tiny-xlib" +version = "0.2.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0324504befd01cab6e0c994f34b2ffa257849ee019d3fb3b64fb2c858887d89e" +dependencies = [ + "as-raw-xcb-connection", + "ctor-lite", + "pkg-config", + "tracing", +] + [[package]] name = "tinystr" version = "0.7.6" @@ -5831,6 +6086,112 @@ dependencies = [ "wasm-bindgen", ] +[[package]] +name = "wgpu" +version = "23.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "80f70000db37c469ea9d67defdc13024ddf9a5f1b89cb2941b812ad7cde1735a" +dependencies = [ + "arrayvec 0.7.6", + "cfg_aliases 0.1.1", + "document-features", + "js-sys", + "log", + "naga", + "parking_lot 0.12.3", + "profiling", + "raw-window-handle 0.6.2", + "smallvec", + "static_assertions", + "wasm-bindgen", + "wasm-bindgen-futures", + "web-sys", + "wgpu-core", + "wgpu-hal", + "wgpu-types", +] + +[[package]] +name = "wgpu-core" +version = "23.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d63c3c478de8e7e01786479919c8769f62a22eec16788d8c2ac77ce2c132778a" +dependencies = [ + "arrayvec 0.7.6", + "bit-vec", + "bitflags 2.6.0", + "cfg_aliases 0.1.1", + "document-features", + "indexmap", + "log", + "naga", + "once_cell", + "parking_lot 0.12.3", + "profiling", + "raw-window-handle 0.6.2", + "rustc-hash 1.1.0", + "smallvec", + "thiserror", + "wgpu-hal", + "wgpu-types", +] + +[[package]] +name = "wgpu-hal" +version = "23.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "89364b8a0b211adc7b16aeaf1bd5ad4a919c1154b44c9ce27838213ba05fd821" +dependencies = [ + "android_system_properties", + "arrayvec 0.7.6", + "ash", + "bit-set", + "bitflags 2.6.0", + "block", + "bytemuck", + "cfg_aliases 0.1.1", + "core-graphics-types 0.1.3", + "glow 0.14.2", + "glutin_wgl_sys 0.6.0", + "gpu-alloc", + "gpu-allocator", + "gpu-descriptor", + "js-sys", + "khronos-egl", + "libc", + "libloading 0.8.5", + "log", + "metal", + "naga", + "ndk-sys 0.5.0+25.2.9519653", + "objc", + "once_cell", + "parking_lot 0.12.3", + "profiling", + "range-alloc", + "raw-window-handle 0.6.2", + "renderdoc-sys", + "rustc-hash 1.1.0", + "smallvec", + "thiserror", + "wasm-bindgen", + "web-sys", + "wgpu-types", + "windows 0.58.0", + "windows-core 0.58.0", +] + +[[package]] +name = "wgpu-types" +version = "23.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "610f6ff27778148c31093f3b03abc4840f9636d58d597ca2f5977433acfe0068" +dependencies = [ + "bitflags 2.6.0", + "js-sys", + "web-sys", +] + [[package]] name = "widestring" version = "1.1.0" @@ -5907,8 +6268,8 @@ version = "0.48.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e686886bc078bc1b0b600cac0147aadb815089b6e4da64016cbd754b6342700f" dependencies = [ - "windows-implement", - "windows-interface", + "windows-implement 0.48.0", + "windows-interface 0.48.0", "windows-targets 0.48.5", ] @@ -5922,6 +6283,16 @@ dependencies = [ "windows-targets 0.52.6", ] +[[package]] +name = "windows" +version = "0.58.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dd04d41d93c4992d421894c18c8b43496aa748dd4c081bac0dc93eb0489272b6" +dependencies = [ + "windows-core 0.58.0", + "windows-targets 0.52.6", +] + [[package]] name = "windows-core" version = "0.52.0" @@ -5937,7 +6308,20 @@ version = "0.54.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "12661b9c89351d684a50a8a643ce5f608e20243b9fb84687800163429f161d65" dependencies = [ - "windows-result", + "windows-result 0.1.2", + "windows-targets 0.52.6", +] + +[[package]] +name = "windows-core" +version = "0.58.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6ba6d44ec8c2591c134257ce647b7ea6b20335bf6379a27dac5f1641fcf59f99" +dependencies = [ + "windows-implement 0.58.0", + "windows-interface 0.58.0", + "windows-result 0.2.0", + "windows-strings", "windows-targets 0.52.6", ] @@ -5952,6 +6336,17 @@ dependencies = [ "syn 1.0.109", ] +[[package]] +name = "windows-implement" +version = "0.58.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2bbd5b46c938e506ecbce286b6628a02171d56153ba733b6c741fc627ec9579b" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.90", +] + [[package]] name = "windows-interface" version = "0.48.0" @@ -5963,6 +6358,17 @@ dependencies = [ "syn 1.0.109", ] +[[package]] +name = "windows-interface" +version = "0.58.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "053c4c462dc91d3b1504c6fe5a726dd15e216ba718e84a0e46a88fbe5ded3515" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.90", +] + [[package]] name = "windows-result" version = "0.1.2" @@ -5972,6 +6378,25 @@ dependencies = [ "windows-targets 0.52.6", ] +[[package]] +name = "windows-result" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1d1043d8214f791817bab27572aaa8af63732e11bf84aa21a45a78d6c317ae0e" +dependencies = [ + "windows-targets 0.52.6", +] + +[[package]] +name = "windows-strings" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4cd9b125c486025df0eabcb585e62173c6c9eddcec5d117d3b6e8c30e2ee4d10" +dependencies = [ + "windows-result 0.2.0", + "windows-targets 0.52.6", +] + [[package]] name = "windows-sys" version = "0.42.0" diff --git a/Cargo.toml b/Cargo.toml index a98a24ab3..6b70605d9 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -22,6 +22,9 @@ members = [ "cargo_nih_plug", "xtask", + "plugins/examples/byo_gui_gl", + "plugins/examples/byo_gui_softbuffer", + "plugins/examples/byo_gui_wgpu", "plugins/examples/gain", "plugins/examples/gain_gui_egui", "plugins/examples/gain_gui_iced", diff --git a/plugins/examples/byo_gui_gl/Cargo.toml b/plugins/examples/byo_gui_gl/Cargo.toml new file mode 100644 index 000000000..7d302465a --- /dev/null +++ b/plugins/examples/byo_gui_gl/Cargo.toml @@ -0,0 +1,22 @@ +[package] +name = "byo_gui_gl" +version = "0.1.0" +edition = "2021" +authors = ["Billy Messenger <60663878+BillyDM@users.noreply.github.com>"] +license = "ISC" + +description = "A simple example plugin with a raw OpenGL context for rendering" + +[lib] +# The `lib` artifact is needed for the standalone target +crate-type = ["cdylib", "lib"] + +[dependencies] +nih_plug = { path = "../../../", features = ["assert_process_allocs", "standalone"] } +baseview = { git = "https://github.com/RustAudio/baseview.git", rev = "9a0b42c09d712777b2edb4c5e0cb6baf21e988f0", features = ["opengl"] } +raw-window-handle = "0.5" +glow = "0.16" +crossbeam = "0.8" +atomic_float = "0.1" +# To make the state persistable +serde = { version = "1.0", features = ["derive"] } \ No newline at end of file diff --git a/plugins/examples/byo_gui_gl/src/lib.rs b/plugins/examples/byo_gui_gl/src/lib.rs new file mode 100644 index 000000000..5f1eb9328 --- /dev/null +++ b/plugins/examples/byo_gui_gl/src/lib.rs @@ -0,0 +1,553 @@ +//! This plugin demonstrates how to "bring your own GUI toolkit" using a raw OpenGL context. + +use baseview::{gl::GlConfig, WindowHandle, WindowOpenOptions, WindowScalePolicy}; +use crossbeam::atomic::AtomicCell; +use nih_plug::params::persist::PersistentField; +use nih_plug::prelude::*; +use raw_window_handle::{HasRawWindowHandle, RawWindowHandle}; +use serde::{Deserialize, Serialize}; +use std::sync::{ + atomic::{AtomicBool, Ordering}, + Arc, +}; + +/// The time it takes for the peak meter to decay by 12 dB after switching to complete silence. +const PEAK_METER_DECAY_MS: f64 = 150.0; + +pub struct CustomGlWindow { + gui_context: Arc, + gl: Arc, + + vertex_array: glow::NativeVertexArray, + program: glow::NativeProgram, + + #[allow(unused)] + params: Arc, + #[allow(unused)] + peak_meter: Arc, +} + +impl Drop for CustomGlWindow { + fn drop(&mut self) { + use glow::HasContext as _; + + unsafe { + self.gl.delete_program(self.program); + self.gl.delete_vertex_array(self.vertex_array); + } + } +} + +impl CustomGlWindow { + fn new( + window: &mut baseview::Window<'_>, + gui_context: Arc, + params: Arc, + peak_meter: Arc, + _scaling_factor: f32, + ) -> Self { + use glow::HasContext as _; + + // TODO: Return an error instead of panicking once baseview gets thats + // ability. + let gl_context = window + .gl_context() + .expect("failed to get baseview gl context"); + + let (gl, vertex_array, program) = unsafe { + gl_context.make_current(); + + #[allow(clippy::arc_with_non_send_sync)] + let gl = Arc::new(glow::Context::from_loader_function(|s| { + gl_context.get_proc_address(s) + })); + + let vertex_array = gl + .create_vertex_array() + .expect("Cannot create vertex array"); + gl.bind_vertex_array(Some(vertex_array)); + + let program = gl.create_program().expect("Cannot create program"); + + let (vertex_shader_source, fragment_shader_source) = ( + r#"const vec2 verts[3] = vec2[3]( + vec2(0.5f, 1.0f), + vec2(0.0f, 0.0f), + vec2(1.0f, 0.0f) + ); + out vec2 vert; + void main() { + vert = verts[gl_VertexID]; + gl_Position = vec4(vert - 0.5, 0.0, 1.0); + }"#, + r#"precision mediump float; + in vec2 vert; + out vec4 color; + void main() { + color = vec4(vert, 0.5, 1.0); + }"#, + ); + + let shader_sources = [ + (glow::VERTEX_SHADER, vertex_shader_source), + (glow::FRAGMENT_SHADER, fragment_shader_source), + ]; + + let mut shaders = Vec::with_capacity(shader_sources.len()); + + for (shader_type, shader_source) in shader_sources.iter() { + let shader = gl + .create_shader(*shader_type) + .expect("Cannot create shader"); + gl.shader_source(shader, &format!("{}\n{}", "#version 130", shader_source)); + gl.compile_shader(shader); + if !gl.get_shader_compile_status(shader) { + panic!("{}", gl.get_shader_info_log(shader)); + } + gl.attach_shader(program, shader); + shaders.push(shader); + } + + gl.link_program(program); + if !gl.get_program_link_status(program) { + panic!("{}", gl.get_program_info_log(program)); + } + + for shader in shaders { + gl.detach_shader(program, shader); + gl.delete_shader(shader); + } + + gl.use_program(Some(program)); + + gl_context.make_not_current(); + + (gl, vertex_array, program) + }; + + Self { + gui_context, + gl, + vertex_array, + program, + params, + peak_meter, + } + } +} + +impl baseview::WindowHandler for CustomGlWindow { + fn on_frame(&mut self, window: &mut baseview::Window) { + use glow::HasContext as _; + // Do rendering here. + + let (_width, _height) = self.params.editor_state.size(); + + let gl_context = window + .gl_context() + .expect("failed to get baseview gl context"); + + unsafe { + gl_context.make_current(); + + self.gl.clear_color(0.05, 0.05, 0.05, 1.0); + self.gl.clear(glow::COLOR_BUFFER_BIT); + + self.gl.draw_arrays(glow::TRIANGLES, 0, 3); + + gl_context.swap_buffers(); + gl_context.make_not_current(); + } + } + + fn on_event( + &mut self, + _window: &mut baseview::Window, + event: baseview::Event, + ) -> baseview::EventStatus { + // Use this to set parameter values. + let _param_setter = ParamSetter::new(self.gui_context.as_ref()); + + match &event { + // Do event processing here. + baseview::Event::Window(event) => match event { + baseview::WindowEvent::Resized(window_info) => { + self.params.editor_state.size.store(( + window_info.logical_size().width.round() as u32, + window_info.logical_size().height.round() as u32, + )); + } + _ => {} + }, + _ => {} + } + + baseview::EventStatus::Captured + } +} + +#[derive(Debug, Serialize, Deserialize)] +pub struct CustomGlEditorState { + /// The window's size in logical pixels before applying `scale_factor`. + #[serde(with = "nih_plug::params::persist::serialize_atomic_cell")] + size: AtomicCell<(u32, u32)>, + /// Whether the editor's window is currently open. + #[serde(skip)] + open: AtomicBool, +} + +impl CustomGlEditorState { + pub fn from_size(size: (u32, u32)) -> Arc { + Arc::new(Self { + size: AtomicCell::new(size), + open: AtomicBool::new(false), + }) + } + + /// Returns a `(width, height)` pair for the current size of the GUI in logical pixels. + pub fn size(&self) -> (u32, u32) { + self.size.load() + } + + /// Whether the GUI is currently visible. + // Called `is_open()` instead of `open()` to avoid the ambiguity. + pub fn is_open(&self) -> bool { + self.open.load(Ordering::Acquire) + } +} + +impl<'a> PersistentField<'a, CustomGlEditorState> for Arc { + fn set(&self, new_value: CustomGlEditorState) { + self.size.store(new_value.size.load()); + } + + fn map(&self, f: F) -> R + where + F: Fn(&CustomGlEditorState) -> R, + { + f(self) + } +} + +pub struct CustomGlEditor { + params: Arc, + peak_meter: Arc, + + /// The scaling factor reported by the host, if any. On macOS this will never be set and we + /// should use the system scaling factor instead. + scaling_factor: AtomicCell>, +} + +impl Editor for CustomGlEditor { + fn spawn( + &self, + parent: ParentWindowHandle, + context: Arc, + ) -> Box { + let (unscaled_width, unscaled_height) = self.params.editor_state.size(); + let scaling_factor = self.scaling_factor.load(); + + let gui_context = Arc::clone(&context); + + let params = Arc::clone(&self.params); + let peak_meter = Arc::clone(&self.peak_meter); + + let window = baseview::Window::open_parented( + &ParentWindowHandleAdapter(parent), + WindowOpenOptions { + title: String::from("OpenGL Window"), + // Baseview should be doing the DPI scaling for us + size: baseview::Size::new(unscaled_width as f64, unscaled_height as f64), + // NOTE: For some reason passing 1.0 here causes the UI to be scaled on macOS but + // not the mouse events. + scale: scaling_factor + .map(|factor| WindowScalePolicy::ScaleFactor(factor as f64)) + .unwrap_or(WindowScalePolicy::SystemScaleFactor), + + gl_config: Some(GlConfig { + version: (3, 2), + red_bits: 8, + blue_bits: 8, + green_bits: 8, + alpha_bits: 8, + depth_bits: 24, + stencil_bits: 8, + samples: None, + srgb: true, + double_buffer: true, + vsync: false, + ..Default::default() + }), + }, + move |window: &mut baseview::Window<'_>| -> CustomGlWindow { + CustomGlWindow::new( + window, + gui_context, + params, + peak_meter, + scaling_factor.unwrap_or(1.0), + ) + }, + ); + + self.params.editor_state.open.store(true, Ordering::Release); + Box::new(CustomGlEditorHandle { + state: self.params.editor_state.clone(), + window, + }) + } + + fn size(&self) -> (u32, u32) { + self.params.editor_state.size() + } + + fn set_scale_factor(&self, factor: f32) -> bool { + // If the editor is currently open then the host must not change the current HiDPI scale as + // we don't have a way to handle that. Ableton Live does this. + if self.params.editor_state.is_open() { + return false; + } + + self.scaling_factor.store(Some(factor)); + true + } + + fn param_value_changed(&self, _id: &str, _normalized_value: f32) { + // As mentioned above, for now we'll always force a redraw to allow meter widgets to work + // correctly. In the future we can use an `Arc` and only force a redraw when + // that boolean is set. + } + + fn param_modulation_changed(&self, _id: &str, _modulation_offset: f32) {} + + fn param_values_changed(&self) { + // Same + } +} + +/// The window handle used for [`EguiEditor`]. +struct CustomGlEditorHandle { + state: Arc, + window: WindowHandle, +} + +/// The window handle enum stored within 'WindowHandle' contains raw pointers. Is there a way around +/// having this requirement? +unsafe impl Send for CustomGlEditorHandle {} + +impl Drop for CustomGlEditorHandle { + fn drop(&mut self) { + self.state.open.store(false, Ordering::Release); + // XXX: This should automatically happen when the handle gets dropped, but apparently not + self.window.close(); + } +} + +/// This version of `baseview` uses a different version of `raw_window_handle than NIH-plug, so we +/// need to adapt it ourselves. +struct ParentWindowHandleAdapter(nih_plug::editor::ParentWindowHandle); + +unsafe impl HasRawWindowHandle for ParentWindowHandleAdapter { + fn raw_window_handle(&self) -> RawWindowHandle { + match self.0 { + ParentWindowHandle::X11Window(window) => { + let mut handle = raw_window_handle::XcbWindowHandle::empty(); + handle.window = window; + RawWindowHandle::Xcb(handle) + } + ParentWindowHandle::AppKitNsView(ns_view) => { + let mut handle = raw_window_handle::AppKitWindowHandle::empty(); + handle.ns_view = ns_view; + RawWindowHandle::AppKit(handle) + } + ParentWindowHandle::Win32Hwnd(hwnd) => { + let mut handle = raw_window_handle::Win32WindowHandle::empty(); + handle.hwnd = hwnd; + RawWindowHandle::Win32(handle) + } + } + } +} + +/// This is mostly identical to the gain example, minus some fluff, and with a GUI. +pub struct MyPlugin { + params: Arc, + + /// Needed to normalize the peak meter's response based on the sample rate. + peak_meter_decay_weight: f32, + /// The current data for the peak meter. This is stored as an [`Arc`] so we can share it between + /// the GUI and the audio processing parts. If you have more state to share, then it's a good + /// idea to put all of that in a struct behind a single `Arc`. + /// + /// This is stored as voltage gain. + peak_meter: Arc, +} + +#[derive(Params)] +pub struct MyPluginParams { + /// The editor state, saved together with the parameter state so the custom scaling can be + /// restored. + #[persist = "editor-state"] + editor_state: Arc, + + #[id = "gain"] + pub gain: FloatParam, + + #[id = "foobar"] + pub some_int: IntParam, +} + +impl Default for MyPlugin { + fn default() -> Self { + Self { + params: Arc::new(MyPluginParams::default()), + + peak_meter_decay_weight: 1.0, + peak_meter: Arc::new(AtomicF32::new(util::MINUS_INFINITY_DB)), + } + } +} + +impl Default for MyPluginParams { + fn default() -> Self { + Self { + editor_state: CustomGlEditorState::from_size((400, 300)), + + // See the main gain example for more details + gain: FloatParam::new( + "Gain", + util::db_to_gain(0.0), + FloatRange::Skewed { + min: util::db_to_gain(-30.0), + max: util::db_to_gain(30.0), + factor: FloatRange::gain_skew_factor(-30.0, 30.0), + }, + ) + .with_smoother(SmoothingStyle::Logarithmic(50.0)) + .with_unit(" dB") + .with_value_to_string(formatters::v2s_f32_gain_to_db(2)) + .with_string_to_value(formatters::s2v_f32_gain_to_db()), + some_int: IntParam::new("Something", 3, IntRange::Linear { min: 0, max: 3 }), + } + } +} + +impl Plugin for MyPlugin { + const NAME: &'static str = "BYO GUI Example (OpenGL)"; + const VENDOR: &'static str = "Moist Plugins GmbH"; + const URL: &'static str = "https://youtu.be/dQw4w9WgXcQ"; + const EMAIL: &'static str = "info@example.com"; + + const VERSION: &'static str = env!("CARGO_PKG_VERSION"); + + const AUDIO_IO_LAYOUTS: &'static [AudioIOLayout] = &[ + AudioIOLayout { + main_input_channels: NonZeroU32::new(2), + main_output_channels: NonZeroU32::new(2), + ..AudioIOLayout::const_default() + }, + AudioIOLayout { + main_input_channels: NonZeroU32::new(1), + main_output_channels: NonZeroU32::new(1), + ..AudioIOLayout::const_default() + }, + ]; + + const SAMPLE_ACCURATE_AUTOMATION: bool = true; + + type SysExMessage = (); + type BackgroundTask = (); + + fn params(&self) -> Arc { + self.params.clone() + } + + fn editor(&mut self, _async_executor: AsyncExecutor) -> Option> { + Some(Box::new(CustomGlEditor { + params: Arc::clone(&self.params), + peak_meter: Arc::clone(&self.peak_meter), + + // TODO: We can't get the size of the window when baseview does its own scaling, so if the + // host does not set a scale factor on Windows or Linux we should just use a factor of + // 1. That may make the GUI tiny but it also prevents it from getting cut off. + #[cfg(target_os = "macos")] + scaling_factor: AtomicCell::new(None), + #[cfg(not(target_os = "macos"))] + scaling_factor: AtomicCell::new(Some(1.0)), + })) + } + + fn initialize( + &mut self, + _audio_io_layout: &AudioIOLayout, + buffer_config: &BufferConfig, + _context: &mut impl InitContext, + ) -> bool { + // After `PEAK_METER_DECAY_MS` milliseconds of pure silence, the peak meter's value should + // have dropped by 12 dB + self.peak_meter_decay_weight = 0.25f64 + .powf((buffer_config.sample_rate as f64 * PEAK_METER_DECAY_MS / 1000.0).recip()) + as f32; + + true + } + + fn process( + &mut self, + buffer: &mut Buffer, + _aux: &mut AuxiliaryBuffers, + _context: &mut impl ProcessContext, + ) -> ProcessStatus { + for channel_samples in buffer.iter_samples() { + let mut amplitude = 0.0; + let num_samples = channel_samples.len(); + + let gain = self.params.gain.smoothed.next(); + for sample in channel_samples { + *sample *= gain; + amplitude += *sample; + } + + // To save resources, a plugin can (and probably should!) only perform expensive + // calculations that are only displayed on the GUI while the GUI is open + if self.params.editor_state.is_open() { + amplitude = (amplitude / num_samples as f32).abs(); + let current_peak_meter = self.peak_meter.load(std::sync::atomic::Ordering::Relaxed); + let new_peak_meter = if amplitude > current_peak_meter { + amplitude + } else { + current_peak_meter * self.peak_meter_decay_weight + + amplitude * (1.0 - self.peak_meter_decay_weight) + }; + + self.peak_meter + .store(new_peak_meter, std::sync::atomic::Ordering::Relaxed) + } + } + + ProcessStatus::Normal + } +} + +impl ClapPlugin for MyPlugin { + const CLAP_ID: &'static str = "com.moist-plugins-gmbh.byo-gui-gl"; + const CLAP_DESCRIPTION: Option<&'static str> = + Some("A simple example plugin with a raw OpenGL context for rendering"); + const CLAP_MANUAL_URL: Option<&'static str> = Some(Self::URL); + const CLAP_SUPPORT_URL: Option<&'static str> = None; + const CLAP_FEATURES: &'static [ClapFeature] = &[ + ClapFeature::AudioEffect, + ClapFeature::Stereo, + ClapFeature::Mono, + ClapFeature::Utility, + ]; +} + +impl Vst3Plugin for MyPlugin { + const VST3_CLASS_ID: [u8; 16] = *b"ByoGuiOpenGLWooo"; + const VST3_SUBCATEGORIES: &'static [Vst3SubCategory] = + &[Vst3SubCategory::Fx, Vst3SubCategory::Tools]; +} + +nih_export_clap!(MyPlugin); +nih_export_vst3!(MyPlugin); diff --git a/plugins/examples/byo_gui_gl/src/main.rs b/plugins/examples/byo_gui_gl/src/main.rs new file mode 100644 index 000000000..0468397bc --- /dev/null +++ b/plugins/examples/byo_gui_gl/src/main.rs @@ -0,0 +1,7 @@ +use nih_plug::prelude::*; + +use byo_gui_gl::MyPlugin; + +fn main() { + nih_export_standalone::(); +} diff --git a/plugins/examples/byo_gui_softbuffer/Cargo.toml b/plugins/examples/byo_gui_softbuffer/Cargo.toml new file mode 100644 index 000000000..4fa27ea14 --- /dev/null +++ b/plugins/examples/byo_gui_softbuffer/Cargo.toml @@ -0,0 +1,23 @@ +[package] +name = "byo_gui_softbuffer" +version = "0.1.0" +edition = "2021" +authors = ["Billy Messenger <60663878+BillyDM@users.noreply.github.com>"] +license = "ISC" + +description = "A simple example plugin with a raw Softbuffer context for rendering" + +[lib] +# The `lib` artifact is needed for the standalone target +crate-type = ["cdylib", "lib"] + +[dependencies] +nih_plug = { path = "../../../", features = ["assert_process_allocs", "standalone"] } +baseview = { git = "https://github.com/RustAudio/baseview.git", rev = "9a0b42c09d712777b2edb4c5e0cb6baf21e988f0" } +softbuffer = { version = "0.4.6", default-features = false, features = ["kms", "x11"]} +raw-window-handle = "0.5" +raw-window-handle-06 = { package = "raw-window-handle", version = "0.6" } +crossbeam = "0.8" +atomic_float = "0.1" +# To make the state persistable +serde = { version = "1.0", features = ["derive"] } \ No newline at end of file diff --git a/plugins/examples/byo_gui_softbuffer/src/lib.rs b/plugins/examples/byo_gui_softbuffer/src/lib.rs new file mode 100644 index 000000000..2d65108d6 --- /dev/null +++ b/plugins/examples/byo_gui_softbuffer/src/lib.rs @@ -0,0 +1,585 @@ +//! This plugin demonstrates how to "bring your own GUI toolkit" using a raw Softbuffer rendering context. + +use baseview::{WindowHandle, WindowOpenOptions, WindowScalePolicy}; +use crossbeam::atomic::AtomicCell; +use nih_plug::params::persist::PersistentField; +use nih_plug::prelude::*; +use raw_window_handle::{HasRawWindowHandle, RawWindowHandle}; +use serde::{Deserialize, Serialize}; +use std::{ + num::NonZeroIsize, + ptr::NonNull, + sync::{ + atomic::{AtomicBool, Ordering}, + Arc, + }, +}; + +/// The time it takes for the peak meter to decay by 12 dB after switching to complete silence. +const PEAK_METER_DECAY_MS: f64 = 150.0; + +pub struct CustomSoftbufferWindow { + gui_context: Arc, + + _sb_context: softbuffer::Context, + sb_surface: softbuffer::Surface, + + physical_width: u32, + physical_height: u32, + + #[allow(unused)] + params: Arc, + #[allow(unused)] + peak_meter: Arc, +} + +impl CustomSoftbufferWindow { + fn new( + window: &mut baseview::Window<'_>, + gui_context: Arc, + params: Arc, + peak_meter: Arc, + scaling_factor: f32, + ) -> Self { + let (unscaled_width, unscaled_height) = params.editor_state.size(); + let physical_width = (unscaled_width as f64 * scaling_factor as f64).round() as u32; + let physical_height = (unscaled_height as f64 * scaling_factor as f64).round() as u32; + + let target = baseview_window_to_surface_target(window); + + let sb_context = + softbuffer::Context::new(target.clone()).expect("could not get softbuffer context"); + let mut sb_surface = softbuffer::Surface::new(&sb_context, target) + .expect("could not create softbuffer surface"); + + sb_surface + .resize( + NonZeroU32::new(physical_width).unwrap(), + NonZeroU32::new(physical_height).unwrap(), + ) + .unwrap(); + + Self { + gui_context, + _sb_context: sb_context, + sb_surface, + physical_width, + physical_height, + params, + peak_meter, + } + } +} + +impl baseview::WindowHandler for CustomSoftbufferWindow { + fn on_frame(&mut self, _window: &mut baseview::Window) { + // Do rendering here. + + let mut buffer = self.sb_surface.buffer_mut().unwrap(); + for y in 0..self.physical_height { + for x in 0..self.physical_width { + let red = x % 255; + let green = y % 255; + let blue = (x * y) % 255; + let index = y as usize * self.physical_width as usize + x as usize; + buffer[index] = blue | (green << 8) | (red << 16); + } + } + + buffer.present().unwrap(); + } + + fn on_event( + &mut self, + _window: &mut baseview::Window, + event: baseview::Event, + ) -> baseview::EventStatus { + // Use this to set parameter values. + let _param_setter = ParamSetter::new(self.gui_context.as_ref()); + + match &event { + // Do event processing here. + baseview::Event::Window(event) => match event { + baseview::WindowEvent::Resized(window_info) => { + self.params.editor_state.size.store(( + window_info.logical_size().width.round() as u32, + window_info.logical_size().height.round() as u32, + )); + + self.physical_width = window_info.physical_size().width; + self.physical_height = window_info.physical_size().height; + + self.sb_surface + .resize( + NonZeroU32::new(self.physical_width).unwrap(), + NonZeroU32::new(self.physical_height).unwrap(), + ) + .unwrap(); + } + _ => {} + }, + _ => {} + } + + baseview::EventStatus::Captured + } +} + +#[derive(Debug, Serialize, Deserialize)] +pub struct CustomSoftbufferEditorState { + /// The window's size in logical pixels before applying `scale_factor`. + #[serde(with = "nih_plug::params::persist::serialize_atomic_cell")] + size: AtomicCell<(u32, u32)>, + /// Whether the editor's window is currently open. + #[serde(skip)] + open: AtomicBool, +} + +impl CustomSoftbufferEditorState { + pub fn from_size(size: (u32, u32)) -> Arc { + Arc::new(Self { + size: AtomicCell::new(size), + open: AtomicBool::new(false), + }) + } + + /// Returns a `(width, height)` pair for the current size of the GUI in logical pixels. + pub fn size(&self) -> (u32, u32) { + self.size.load() + } + + /// Whether the GUI is currently visible. + // Called `is_open()` instead of `open()` to avoid the ambiguity. + pub fn is_open(&self) -> bool { + self.open.load(Ordering::Acquire) + } +} + +impl<'a> PersistentField<'a, CustomSoftbufferEditorState> for Arc { + fn set(&self, new_value: CustomSoftbufferEditorState) { + self.size.store(new_value.size.load()); + } + + fn map(&self, f: F) -> R + where + F: Fn(&CustomSoftbufferEditorState) -> R, + { + f(self) + } +} + +pub struct CustomSoftbufferEditor { + params: Arc, + peak_meter: Arc, + + /// The scaling factor reported by the host, if any. On macOS this will never be set and we + /// should use the system scaling factor instead. + scaling_factor: AtomicCell>, +} + +impl Editor for CustomSoftbufferEditor { + fn spawn( + &self, + parent: ParentWindowHandle, + context: Arc, + ) -> Box { + let (unscaled_width, unscaled_height) = self.params.editor_state.size(); + let scaling_factor = self.scaling_factor.load(); + + let gui_context = Arc::clone(&context); + + let params = Arc::clone(&self.params); + let peak_meter = Arc::clone(&self.peak_meter); + + let window = baseview::Window::open_parented( + &ParentWindowHandleAdapter(parent), + WindowOpenOptions { + title: String::from("Softbuffer Window"), + // Baseview should be doing the DPI scaling for us + size: baseview::Size::new(unscaled_width as f64, unscaled_height as f64), + // NOTE: For some reason passing 1.0 here causes the UI to be scaled on macOS but + // not the mouse events. + scale: scaling_factor + .map(|factor| WindowScalePolicy::ScaleFactor(factor as f64)) + .unwrap_or(WindowScalePolicy::SystemScaleFactor), + }, + move |window: &mut baseview::Window<'_>| -> CustomSoftbufferWindow { + CustomSoftbufferWindow::new( + window, + gui_context, + params, + peak_meter, + scaling_factor.unwrap_or(1.0), + ) + }, + ); + + self.params.editor_state.open.store(true, Ordering::Release); + Box::new(CustomSoftbufferEditorHandle { + state: self.params.editor_state.clone(), + window, + }) + } + + fn size(&self) -> (u32, u32) { + self.params.editor_state.size() + } + + fn set_scale_factor(&self, factor: f32) -> bool { + // If the editor is currently open then the host must not change the current HiDPI scale as + // we don't have a way to handle that. Ableton Live does this. + if self.params.editor_state.is_open() { + return false; + } + + self.scaling_factor.store(Some(factor)); + true + } + + fn param_value_changed(&self, _id: &str, _normalized_value: f32) { + // As mentioned above, for now we'll always force a redraw to allow meter widgets to work + // correctly. In the future we can use an `Arc` and only force a redraw when + // that boolean is set. + } + + fn param_modulation_changed(&self, _id: &str, _modulation_offset: f32) {} + + fn param_values_changed(&self) { + // Same + } +} + +/// The window handle used for [`EguiEditor`]. +struct CustomSoftbufferEditorHandle { + state: Arc, + window: WindowHandle, +} + +/// The window handle enum stored within 'WindowHandle' contains raw pointers. Is there a way around +/// having this requirement? +unsafe impl Send for CustomSoftbufferEditorHandle {} + +impl Drop for CustomSoftbufferEditorHandle { + fn drop(&mut self) { + self.state.open.store(false, Ordering::Release); + // XXX: This should automatically happen when the handle gets dropped, but apparently not + self.window.close(); + } +} + +/// This version of `baseview` uses a different version of `raw_window_handle than NIH-plug, so we +/// need to adapt it ourselves. +struct ParentWindowHandleAdapter(nih_plug::editor::ParentWindowHandle); + +unsafe impl HasRawWindowHandle for ParentWindowHandleAdapter { + fn raw_window_handle(&self) -> RawWindowHandle { + match self.0 { + ParentWindowHandle::X11Window(window) => { + let mut handle = raw_window_handle::XcbWindowHandle::empty(); + handle.window = window; + RawWindowHandle::Xcb(handle) + } + ParentWindowHandle::AppKitNsView(ns_view) => { + let mut handle = raw_window_handle::AppKitWindowHandle::empty(); + handle.ns_view = ns_view; + RawWindowHandle::AppKit(handle) + } + ParentWindowHandle::Win32Hwnd(hwnd) => { + let mut handle = raw_window_handle::Win32WindowHandle::empty(); + handle.hwnd = hwnd; + RawWindowHandle::Win32(handle) + } + } + } +} + +/// Softbuffer uses raw_window_handle v6, but baseview uses raw_window_handle v5, so we need to +/// adapt it ourselves. +#[derive(Clone)] +struct SoftbufferWindowHandleAdapter { + raw_display_handle: raw_window_handle_06::RawDisplayHandle, + raw_window_handle: raw_window_handle_06::RawWindowHandle, +} + +impl raw_window_handle_06::HasDisplayHandle for SoftbufferWindowHandleAdapter { + fn display_handle( + &self, + ) -> Result, raw_window_handle_06::HandleError> { + unsafe { + Ok(raw_window_handle_06::DisplayHandle::borrow_raw( + self.raw_display_handle, + )) + } + } +} + +impl raw_window_handle_06::HasWindowHandle for SoftbufferWindowHandleAdapter { + fn window_handle( + &self, + ) -> Result, raw_window_handle_06::HandleError> { + unsafe { + Ok(raw_window_handle_06::WindowHandle::borrow_raw( + self.raw_window_handle, + )) + } + } +} + +fn baseview_window_to_surface_target( + window: &baseview::Window<'_>, +) -> SoftbufferWindowHandleAdapter { + use raw_window_handle::{HasRawDisplayHandle, HasRawWindowHandle}; + + let raw_display_handle = window.raw_display_handle(); + let raw_window_handle = window.raw_window_handle(); + + SoftbufferWindowHandleAdapter { + raw_display_handle: match raw_display_handle { + raw_window_handle::RawDisplayHandle::AppKit(_) => { + raw_window_handle_06::RawDisplayHandle::AppKit( + raw_window_handle_06::AppKitDisplayHandle::new(), + ) + } + raw_window_handle::RawDisplayHandle::Xlib(handle) => { + raw_window_handle_06::RawDisplayHandle::Xlib( + raw_window_handle_06::XlibDisplayHandle::new( + NonNull::new(handle.display), + handle.screen, + ), + ) + } + raw_window_handle::RawDisplayHandle::Xcb(handle) => { + raw_window_handle_06::RawDisplayHandle::Xcb( + raw_window_handle_06::XcbDisplayHandle::new( + NonNull::new(handle.connection), + handle.screen, + ), + ) + } + raw_window_handle::RawDisplayHandle::Windows(_) => { + raw_window_handle_06::RawDisplayHandle::Windows( + raw_window_handle_06::WindowsDisplayHandle::new(), + ) + } + _ => todo!(), + }, + raw_window_handle: match raw_window_handle { + raw_window_handle::RawWindowHandle::AppKit(handle) => { + raw_window_handle_06::RawWindowHandle::AppKit( + raw_window_handle_06::AppKitWindowHandle::new( + NonNull::new(handle.ns_view).unwrap(), + ), + ) + } + raw_window_handle::RawWindowHandle::Xlib(handle) => { + raw_window_handle_06::RawWindowHandle::Xlib( + raw_window_handle_06::XlibWindowHandle::new(handle.window), + ) + } + raw_window_handle::RawWindowHandle::Xcb(handle) => { + raw_window_handle_06::RawWindowHandle::Xcb( + raw_window_handle_06::XcbWindowHandle::new( + NonZeroU32::new(handle.window).unwrap(), + ), + ) + } + raw_window_handle::RawWindowHandle::Win32(handle) => { + // will this work? i have no idea! + let mut raw_handle = raw_window_handle_06::Win32WindowHandle::new( + NonZeroIsize::new(handle.hwnd as isize).unwrap(), + ); + + raw_handle.hinstance = handle + .hinstance + .is_null() + .then(|| NonZeroIsize::new(handle.hinstance as isize).unwrap()); + + raw_window_handle_06::RawWindowHandle::Win32(raw_handle) + } + _ => todo!(), + }, + } +} + +/// This is mostly identical to the gain example, minus some fluff, and with a GUI. +pub struct MyPlugin { + params: Arc, + + /// Needed to normalize the peak meter's response based on the sample rate. + peak_meter_decay_weight: f32, + /// The current data for the peak meter. This is stored as an [`Arc`] so we can share it between + /// the GUI and the audio processing parts. If you have more state to share, then it's a good + /// idea to put all of that in a struct behind a single `Arc`. + /// + /// This is stored as voltage gain. + peak_meter: Arc, +} + +#[derive(Params)] +pub struct MyPluginParams { + /// The editor state, saved together with the parameter state so the custom scaling can be + /// restored. + #[persist = "editor-state"] + editor_state: Arc, + + #[id = "gain"] + pub gain: FloatParam, + + #[id = "foobar"] + pub some_int: IntParam, +} + +impl Default for MyPlugin { + fn default() -> Self { + Self { + params: Arc::new(MyPluginParams::default()), + + peak_meter_decay_weight: 1.0, + peak_meter: Arc::new(AtomicF32::new(util::MINUS_INFINITY_DB)), + } + } +} + +impl Default for MyPluginParams { + fn default() -> Self { + Self { + editor_state: CustomSoftbufferEditorState::from_size((200, 150)), + + // See the main gain example for more details + gain: FloatParam::new( + "Gain", + util::db_to_gain(0.0), + FloatRange::Skewed { + min: util::db_to_gain(-30.0), + max: util::db_to_gain(30.0), + factor: FloatRange::gain_skew_factor(-30.0, 30.0), + }, + ) + .with_smoother(SmoothingStyle::Logarithmic(50.0)) + .with_unit(" dB") + .with_value_to_string(formatters::v2s_f32_gain_to_db(2)) + .with_string_to_value(formatters::s2v_f32_gain_to_db()), + some_int: IntParam::new("Something", 3, IntRange::Linear { min: 0, max: 3 }), + } + } +} + +impl Plugin for MyPlugin { + const NAME: &'static str = "BYO GUI Example (Softbuffer)"; + const VENDOR: &'static str = "Moist Plugins GmbH"; + const URL: &'static str = "https://youtu.be/dQw4w9WgXcQ"; + const EMAIL: &'static str = "info@example.com"; + + const VERSION: &'static str = env!("CARGO_PKG_VERSION"); + + const AUDIO_IO_LAYOUTS: &'static [AudioIOLayout] = &[ + AudioIOLayout { + main_input_channels: NonZeroU32::new(2), + main_output_channels: NonZeroU32::new(2), + ..AudioIOLayout::const_default() + }, + AudioIOLayout { + main_input_channels: NonZeroU32::new(1), + main_output_channels: NonZeroU32::new(1), + ..AudioIOLayout::const_default() + }, + ]; + + const SAMPLE_ACCURATE_AUTOMATION: bool = true; + + type SysExMessage = (); + type BackgroundTask = (); + + fn params(&self) -> Arc { + self.params.clone() + } + + fn editor(&mut self, _async_executor: AsyncExecutor) -> Option> { + Some(Box::new(CustomSoftbufferEditor { + params: Arc::clone(&self.params), + peak_meter: Arc::clone(&self.peak_meter), + + // TODO: We can't get the size of the window when baseview does its own scaling, so if the + // host does not set a scale factor on Windows or Linux we should just use a factor of + // 1. That may make the GUI tiny but it also prevents it from getting cut off. + #[cfg(target_os = "macos")] + scaling_factor: AtomicCell::new(None), + #[cfg(not(target_os = "macos"))] + scaling_factor: AtomicCell::new(Some(1.0)), + })) + } + + fn initialize( + &mut self, + _audio_io_layout: &AudioIOLayout, + buffer_config: &BufferConfig, + _context: &mut impl InitContext, + ) -> bool { + // After `PEAK_METER_DECAY_MS` milliseconds of pure silence, the peak meter's value should + // have dropped by 12 dB + self.peak_meter_decay_weight = 0.25f64 + .powf((buffer_config.sample_rate as f64 * PEAK_METER_DECAY_MS / 1000.0).recip()) + as f32; + + true + } + + fn process( + &mut self, + buffer: &mut Buffer, + _aux: &mut AuxiliaryBuffers, + _context: &mut impl ProcessContext, + ) -> ProcessStatus { + for channel_samples in buffer.iter_samples() { + let mut amplitude = 0.0; + let num_samples = channel_samples.len(); + + let gain = self.params.gain.smoothed.next(); + for sample in channel_samples { + *sample *= gain; + amplitude += *sample; + } + + // To save resources, a plugin can (and probably should!) only perform expensive + // calculations that are only displayed on the GUI while the GUI is open + if self.params.editor_state.is_open() { + amplitude = (amplitude / num_samples as f32).abs(); + let current_peak_meter = self.peak_meter.load(std::sync::atomic::Ordering::Relaxed); + let new_peak_meter = if amplitude > current_peak_meter { + amplitude + } else { + current_peak_meter * self.peak_meter_decay_weight + + amplitude * (1.0 - self.peak_meter_decay_weight) + }; + + self.peak_meter + .store(new_peak_meter, std::sync::atomic::Ordering::Relaxed) + } + } + + ProcessStatus::Normal + } +} + +impl ClapPlugin for MyPlugin { + const CLAP_ID: &'static str = "com.moist-plugins-gmbh.byo-gui-softbuffer"; + const CLAP_DESCRIPTION: Option<&'static str> = + Some("A simple example plugin with a raw Softbuffer context for rendering"); + const CLAP_MANUAL_URL: Option<&'static str> = Some(Self::URL); + const CLAP_SUPPORT_URL: Option<&'static str> = None; + const CLAP_FEATURES: &'static [ClapFeature] = &[ + ClapFeature::AudioEffect, + ClapFeature::Stereo, + ClapFeature::Mono, + ClapFeature::Utility, + ]; +} + +impl Vst3Plugin for MyPlugin { + const VST3_CLASS_ID: [u8; 16] = *b"ByoGuiSoftbuffer"; + const VST3_SUBCATEGORIES: &'static [Vst3SubCategory] = + &[Vst3SubCategory::Fx, Vst3SubCategory::Tools]; +} + +nih_export_clap!(MyPlugin); +nih_export_vst3!(MyPlugin); diff --git a/plugins/examples/byo_gui_softbuffer/src/main.rs b/plugins/examples/byo_gui_softbuffer/src/main.rs new file mode 100644 index 000000000..625da05e9 --- /dev/null +++ b/plugins/examples/byo_gui_softbuffer/src/main.rs @@ -0,0 +1,7 @@ +use nih_plug::prelude::*; + +use byo_gui_softbuffer::MyPlugin; + +fn main() { + nih_export_standalone::(); +} diff --git a/plugins/examples/byo_gui_wgpu/Cargo.toml b/plugins/examples/byo_gui_wgpu/Cargo.toml new file mode 100644 index 000000000..1cd58bf91 --- /dev/null +++ b/plugins/examples/byo_gui_wgpu/Cargo.toml @@ -0,0 +1,24 @@ +[package] +name = "byo_gui_wgpu" +version = "0.1.0" +edition = "2021" +authors = ["Billy Messenger <60663878+BillyDM@users.noreply.github.com>"] +license = "ISC" + +description = "A simple example plugin with a raw WGPU context for rendering" + +[lib] +# The `lib` artifact is needed for the standalone target +crate-type = ["cdylib", "lib"] + +[dependencies] +nih_plug = { path = "../../../", features = ["assert_process_allocs", "standalone"] } +baseview = { git = "https://github.com/RustAudio/baseview.git", rev = "9a0b42c09d712777b2edb4c5e0cb6baf21e988f0" } +wgpu = "23" +raw-window-handle = "0.5" +raw-window-handle-06 = { package = "raw-window-handle", version = "0.6" } +pollster = "0.4.0" +crossbeam = "0.8" +atomic_float = "0.1" +# To make the state persistable +serde = { version = "1.0", features = ["derive"] } \ No newline at end of file diff --git a/plugins/examples/byo_gui_wgpu/src/lib.rs b/plugins/examples/byo_gui_wgpu/src/lib.rs new file mode 100644 index 000000000..0c5333237 --- /dev/null +++ b/plugins/examples/byo_gui_wgpu/src/lib.rs @@ -0,0 +1,673 @@ +//! This plugin demonstrates how to "bring your own GUI toolkit" using a raw WGPU context. + +use baseview::{WindowHandle, WindowOpenOptions, WindowScalePolicy}; +use crossbeam::atomic::AtomicCell; +use nih_plug::params::persist::PersistentField; +use nih_plug::prelude::*; +use raw_window_handle::{HasRawWindowHandle, RawWindowHandle}; +use serde::{Deserialize, Serialize}; +use std::{ + borrow::Cow, + num::NonZeroIsize, + ptr::NonNull, + sync::{ + atomic::{AtomicBool, Ordering}, + Arc, + }, +}; +use wgpu::SurfaceTargetUnsafe; + +/// The time it takes for the peak meter to decay by 12 dB after switching to complete silence. +const PEAK_METER_DECAY_MS: f64 = 150.0; + +pub struct CustomWgpuWindow { + gui_context: Arc, + + device: wgpu::Device, + queue: wgpu::Queue, + pipeline: wgpu::RenderPipeline, + surface: wgpu::Surface<'static>, + surface_config: wgpu::SurfaceConfiguration, + + #[allow(unused)] + params: Arc, + #[allow(unused)] + peak_meter: Arc, +} + +impl CustomWgpuWindow { + fn new( + window: &mut baseview::Window<'_>, + gui_context: Arc, + params: Arc, + peak_meter: Arc, + scaling_factor: f32, + ) -> Self { + let target = baseview_window_to_surface_target(window); + + pollster::block_on(Self::create( + target, + gui_context, + params, + peak_meter, + scaling_factor, + )) + } + + async fn create( + target: SurfaceTargetUnsafe, + gui_context: Arc, + params: Arc, + peak_meter: Arc, + scaling_factor: f32, + ) -> Self { + let (unscaled_width, unscaled_height) = params.editor_state.size(); + let width = (unscaled_width as f64 * scaling_factor as f64).round() as u32; + let height = (unscaled_height as f64 * scaling_factor as f64).round() as u32; + + let instance = wgpu::Instance::new(wgpu::InstanceDescriptor::default()); + + let surface = unsafe { instance.create_surface_unsafe(target) }.unwrap(); + + let adapter = instance + .request_adapter(&wgpu::RequestAdapterOptions { + power_preference: wgpu::PowerPreference::LowPower, + force_fallback_adapter: false, + // Request an adapter which can render to our surface + compatible_surface: Some(&surface), + }) + .await + .expect("Failed to find an appropriate adapter"); + + // Create the logical device and command queue + let (device, queue) = adapter + .request_device( + &wgpu::DeviceDescriptor { + label: None, + required_features: wgpu::Features::empty(), + required_limits: wgpu::Limits::downlevel_webgl2_defaults() + .using_resolution(adapter.limits()), + memory_hints: wgpu::MemoryHints::MemoryUsage, + }, + None, + ) + .await + .expect("Failed to create device"); + + const SHADER: &str = " + const VERTS = array( + vec2(0.5, 1.0), + vec2(0.0, 0.0), + vec2(1.0, 0.0) + ); + + struct VertexOutput { + @builtin(position) clip_position: vec4, + @location(0) position: vec2, + }; + + @vertex + fn vs_main( + @builtin(vertex_index) in_vertex_index: u32, + ) -> VertexOutput { + var out: VertexOutput; + out.position = VERTS[in_vertex_index]; + out.clip_position = vec4(out.position - 0.5, 0.0, 1.0); + return out; + } + + @fragment + fn fs_main(in: VertexOutput) -> @location(0) vec4 { + return vec4(in.position, 0.5, 1.0); + } + "; + + let shader = device.create_shader_module(wgpu::ShaderModuleDescriptor { + label: None, + source: wgpu::ShaderSource::Wgsl(Cow::Borrowed(SHADER)), + }); + + let pipeline_layout = device.create_pipeline_layout(&wgpu::PipelineLayoutDescriptor { + label: None, + bind_group_layouts: &[], + push_constant_ranges: &[], + }); + + let swapchain_capabilities = surface.get_capabilities(&adapter); + let swapchain_format = swapchain_capabilities.formats[0]; + + let pipeline = device.create_render_pipeline(&wgpu::RenderPipelineDescriptor { + label: None, + layout: Some(&pipeline_layout), + vertex: wgpu::VertexState { + module: &shader, + entry_point: Some("vs_main"), + buffers: &[], + compilation_options: Default::default(), + }, + fragment: Some(wgpu::FragmentState { + module: &shader, + entry_point: Some("fs_main"), + compilation_options: Default::default(), + targets: &[Some(swapchain_format.into())], + }), + primitive: wgpu::PrimitiveState::default(), + depth_stencil: None, + multisample: wgpu::MultisampleState::default(), + multiview: None, + cache: None, + }); + + let surface_config = surface.get_default_config(&adapter, width, height).unwrap(); + surface.configure(&device, &surface_config); + + Self { + gui_context, + device, + queue, + pipeline, + surface, + surface_config, + params, + peak_meter, + } + } +} + +impl baseview::WindowHandler for CustomWgpuWindow { + fn on_frame(&mut self, _window: &mut baseview::Window) { + // Do rendering here. + + let frame = self + .surface + .get_current_texture() + .expect("Failed to acquire next swap chain texture"); + let view = frame + .texture + .create_view(&wgpu::TextureViewDescriptor::default()); + let mut encoder = self + .device + .create_command_encoder(&wgpu::CommandEncoderDescriptor { label: None }); + + { + let mut rpass = encoder.begin_render_pass(&wgpu::RenderPassDescriptor { + label: None, + color_attachments: &[Some(wgpu::RenderPassColorAttachment { + view: &view, + resolve_target: None, + ops: wgpu::Operations { + load: wgpu::LoadOp::Clear(wgpu::Color::BLACK), + store: wgpu::StoreOp::Store, + }, + })], + depth_stencil_attachment: None, + timestamp_writes: None, + occlusion_query_set: None, + }); + + rpass.set_pipeline(&self.pipeline); + rpass.draw(0..3, 0..1); + } + + self.queue.submit(Some(encoder.finish())); + frame.present(); + } + + fn on_event( + &mut self, + _window: &mut baseview::Window, + event: baseview::Event, + ) -> baseview::EventStatus { + // Use this to set parameter values. + let _param_setter = ParamSetter::new(self.gui_context.as_ref()); + + match &event { + // Do event processing here. + baseview::Event::Window(event) => match event { + baseview::WindowEvent::Resized(window_info) => { + self.params.editor_state.size.store(( + window_info.logical_size().width.round() as u32, + window_info.logical_size().height.round() as u32, + )); + + self.surface_config.width = window_info.physical_size().width; + self.surface_config.height = window_info.physical_size().height; + + self.surface.configure(&self.device, &self.surface_config); + } + _ => {} + }, + _ => {} + } + + baseview::EventStatus::Captured + } +} + +#[derive(Debug, Serialize, Deserialize)] +pub struct CustomWgpuEditorState { + /// The window's size in logical pixels before applying `scale_factor`. + #[serde(with = "nih_plug::params::persist::serialize_atomic_cell")] + size: AtomicCell<(u32, u32)>, + /// Whether the editor's window is currently open. + #[serde(skip)] + open: AtomicBool, +} + +impl CustomWgpuEditorState { + pub fn from_size(size: (u32, u32)) -> Arc { + Arc::new(Self { + size: AtomicCell::new(size), + open: AtomicBool::new(false), + }) + } + + /// Returns a `(width, height)` pair for the current size of the GUI in logical pixels. + pub fn size(&self) -> (u32, u32) { + self.size.load() + } + + /// Whether the GUI is currently visible. + // Called `is_open()` instead of `open()` to avoid the ambiguity. + pub fn is_open(&self) -> bool { + self.open.load(Ordering::Acquire) + } +} + +impl<'a> PersistentField<'a, CustomWgpuEditorState> for Arc { + fn set(&self, new_value: CustomWgpuEditorState) { + self.size.store(new_value.size.load()); + } + + fn map(&self, f: F) -> R + where + F: Fn(&CustomWgpuEditorState) -> R, + { + f(self) + } +} + +pub struct CustomWgpuEditor { + params: Arc, + peak_meter: Arc, + + /// The scaling factor reported by the host, if any. On macOS this will never be set and we + /// should use the system scaling factor instead. + scaling_factor: AtomicCell>, +} + +impl Editor for CustomWgpuEditor { + fn spawn( + &self, + parent: ParentWindowHandle, + context: Arc, + ) -> Box { + let (unscaled_width, unscaled_height) = self.params.editor_state.size(); + let scaling_factor = self.scaling_factor.load(); + + let gui_context = Arc::clone(&context); + + let params = Arc::clone(&self.params); + let peak_meter = Arc::clone(&self.peak_meter); + + let window = baseview::Window::open_parented( + &ParentWindowHandleAdapter(parent), + WindowOpenOptions { + title: String::from("WGPU Window"), + // Baseview should be doing the DPI scaling for us + size: baseview::Size::new(unscaled_width as f64, unscaled_height as f64), + // NOTE: For some reason passing 1.0 here causes the UI to be scaled on macOS but + // not the mouse events. + scale: scaling_factor + .map(|factor| WindowScalePolicy::ScaleFactor(factor as f64)) + .unwrap_or(WindowScalePolicy::SystemScaleFactor), + }, + move |window: &mut baseview::Window<'_>| -> CustomWgpuWindow { + CustomWgpuWindow::new( + window, + gui_context, + params, + peak_meter, + scaling_factor.unwrap_or(1.0), + ) + }, + ); + + self.params.editor_state.open.store(true, Ordering::Release); + Box::new(CustomWgpuEditorHandle { + state: self.params.editor_state.clone(), + window, + }) + } + + fn size(&self) -> (u32, u32) { + self.params.editor_state.size() + } + + fn set_scale_factor(&self, factor: f32) -> bool { + // If the editor is currently open then the host must not change the current HiDPI scale as + // we don't have a way to handle that. Ableton Live does this. + if self.params.editor_state.is_open() { + return false; + } + + self.scaling_factor.store(Some(factor)); + true + } + + fn param_value_changed(&self, _id: &str, _normalized_value: f32) { + // As mentioned above, for now we'll always force a redraw to allow meter widgets to work + // correctly. In the future we can use an `Arc` and only force a redraw when + // that boolean is set. + } + + fn param_modulation_changed(&self, _id: &str, _modulation_offset: f32) {} + + fn param_values_changed(&self) { + // Same + } +} + +/// The window handle used for [`EguiEditor`]. +struct CustomWgpuEditorHandle { + state: Arc, + window: WindowHandle, +} + +/// The window handle enum stored within 'WindowHandle' contains raw pointers. Is there a way around +/// having this requirement? +unsafe impl Send for CustomWgpuEditorHandle {} + +impl Drop for CustomWgpuEditorHandle { + fn drop(&mut self) { + self.state.open.store(false, Ordering::Release); + // XXX: This should automatically happen when the handle gets dropped, but apparently not + self.window.close(); + } +} + +/// This version of `baseview` uses a different version of `raw_window_handle than NIH-plug, so we +/// need to adapt it ourselves. +struct ParentWindowHandleAdapter(nih_plug::editor::ParentWindowHandle); + +unsafe impl HasRawWindowHandle for ParentWindowHandleAdapter { + fn raw_window_handle(&self) -> RawWindowHandle { + match self.0 { + ParentWindowHandle::X11Window(window) => { + let mut handle = raw_window_handle::XcbWindowHandle::empty(); + handle.window = window; + RawWindowHandle::Xcb(handle) + } + ParentWindowHandle::AppKitNsView(ns_view) => { + let mut handle = raw_window_handle::AppKitWindowHandle::empty(); + handle.ns_view = ns_view; + RawWindowHandle::AppKit(handle) + } + ParentWindowHandle::Win32Hwnd(hwnd) => { + let mut handle = raw_window_handle::Win32WindowHandle::empty(); + handle.hwnd = hwnd; + RawWindowHandle::Win32(handle) + } + } + } +} + +/// WGPU uses raw_window_handle v6, but baseview uses raw_window_handle v5, so manually convert it. +fn baseview_window_to_surface_target(window: &baseview::Window<'_>) -> wgpu::SurfaceTargetUnsafe { + use raw_window_handle::{HasRawDisplayHandle, HasRawWindowHandle}; + + let raw_display_handle = window.raw_display_handle(); + let raw_window_handle = window.raw_window_handle(); + + wgpu::SurfaceTargetUnsafe::RawHandle { + raw_display_handle: match raw_display_handle { + raw_window_handle::RawDisplayHandle::AppKit(_) => { + raw_window_handle_06::RawDisplayHandle::AppKit( + raw_window_handle_06::AppKitDisplayHandle::new(), + ) + } + raw_window_handle::RawDisplayHandle::Xlib(handle) => { + raw_window_handle_06::RawDisplayHandle::Xlib( + raw_window_handle_06::XlibDisplayHandle::new( + NonNull::new(handle.display), + handle.screen, + ), + ) + } + raw_window_handle::RawDisplayHandle::Xcb(handle) => { + raw_window_handle_06::RawDisplayHandle::Xcb( + raw_window_handle_06::XcbDisplayHandle::new( + NonNull::new(handle.connection), + handle.screen, + ), + ) + } + raw_window_handle::RawDisplayHandle::Windows(_) => { + raw_window_handle_06::RawDisplayHandle::Windows( + raw_window_handle_06::WindowsDisplayHandle::new(), + ) + } + _ => todo!(), + }, + raw_window_handle: match raw_window_handle { + raw_window_handle::RawWindowHandle::AppKit(handle) => { + raw_window_handle_06::RawWindowHandle::AppKit( + raw_window_handle_06::AppKitWindowHandle::new( + NonNull::new(handle.ns_view).unwrap(), + ), + ) + } + raw_window_handle::RawWindowHandle::Xlib(handle) => { + raw_window_handle_06::RawWindowHandle::Xlib( + raw_window_handle_06::XlibWindowHandle::new(handle.window), + ) + } + raw_window_handle::RawWindowHandle::Xcb(handle) => { + raw_window_handle_06::RawWindowHandle::Xcb( + raw_window_handle_06::XcbWindowHandle::new( + NonZeroU32::new(handle.window).unwrap(), + ), + ) + } + raw_window_handle::RawWindowHandle::Win32(handle) => { + // will this work? i have no idea! + let mut raw_handle = raw_window_handle_06::Win32WindowHandle::new( + NonZeroIsize::new(handle.hwnd as isize).unwrap(), + ); + + raw_handle.hinstance = handle + .hinstance + .is_null() + .then(|| NonZeroIsize::new(handle.hinstance as isize).unwrap()); + + raw_window_handle_06::RawWindowHandle::Win32(raw_handle) + } + _ => todo!(), + }, + } +} + +/// This is mostly identical to the gain example, minus some fluff, and with a GUI. +pub struct MyPlugin { + params: Arc, + + /// Needed to normalize the peak meter's response based on the sample rate. + peak_meter_decay_weight: f32, + /// The current data for the peak meter. This is stored as an [`Arc`] so we can share it between + /// the GUI and the audio processing parts. If you have more state to share, then it's a good + /// idea to put all of that in a struct behind a single `Arc`. + /// + /// This is stored as voltage gain. + peak_meter: Arc, +} + +#[derive(Params)] +pub struct MyPluginParams { + /// The editor state, saved together with the parameter state so the custom scaling can be + /// restored. + #[persist = "editor-state"] + editor_state: Arc, + + #[id = "gain"] + pub gain: FloatParam, + + #[id = "foobar"] + pub some_int: IntParam, +} + +impl Default for MyPlugin { + fn default() -> Self { + Self { + params: Arc::new(MyPluginParams::default()), + + peak_meter_decay_weight: 1.0, + peak_meter: Arc::new(AtomicF32::new(util::MINUS_INFINITY_DB)), + } + } +} + +impl Default for MyPluginParams { + fn default() -> Self { + Self { + editor_state: CustomWgpuEditorState::from_size((400, 300)), + + // See the main gain example for more details + gain: FloatParam::new( + "Gain", + util::db_to_gain(0.0), + FloatRange::Skewed { + min: util::db_to_gain(-30.0), + max: util::db_to_gain(30.0), + factor: FloatRange::gain_skew_factor(-30.0, 30.0), + }, + ) + .with_smoother(SmoothingStyle::Logarithmic(50.0)) + .with_unit(" dB") + .with_value_to_string(formatters::v2s_f32_gain_to_db(2)) + .with_string_to_value(formatters::s2v_f32_gain_to_db()), + some_int: IntParam::new("Something", 3, IntRange::Linear { min: 0, max: 3 }), + } + } +} + +impl Plugin for MyPlugin { + const NAME: &'static str = "BYO GUI Example (WGPU)"; + const VENDOR: &'static str = "Moist Plugins GmbH"; + const URL: &'static str = "https://youtu.be/dQw4w9WgXcQ"; + const EMAIL: &'static str = "info@example.com"; + + const VERSION: &'static str = env!("CARGO_PKG_VERSION"); + + const AUDIO_IO_LAYOUTS: &'static [AudioIOLayout] = &[ + AudioIOLayout { + main_input_channels: NonZeroU32::new(2), + main_output_channels: NonZeroU32::new(2), + ..AudioIOLayout::const_default() + }, + AudioIOLayout { + main_input_channels: NonZeroU32::new(1), + main_output_channels: NonZeroU32::new(1), + ..AudioIOLayout::const_default() + }, + ]; + + const SAMPLE_ACCURATE_AUTOMATION: bool = true; + + type SysExMessage = (); + type BackgroundTask = (); + + fn params(&self) -> Arc { + self.params.clone() + } + + fn editor(&mut self, _async_executor: AsyncExecutor) -> Option> { + Some(Box::new(CustomWgpuEditor { + params: Arc::clone(&self.params), + peak_meter: Arc::clone(&self.peak_meter), + + // TODO: We can't get the size of the window when baseview does its own scaling, so if the + // host does not set a scale factor on Windows or Linux we should just use a factor of + // 1. That may make the GUI tiny but it also prevents it from getting cut off. + #[cfg(target_os = "macos")] + scaling_factor: AtomicCell::new(None), + #[cfg(not(target_os = "macos"))] + scaling_factor: AtomicCell::new(Some(1.0)), + })) + } + + fn initialize( + &mut self, + _audio_io_layout: &AudioIOLayout, + buffer_config: &BufferConfig, + _context: &mut impl InitContext, + ) -> bool { + // TODO: Figure out a way to disable log spam from wgpu. + + // After `PEAK_METER_DECAY_MS` milliseconds of pure silence, the peak meter's value should + // have dropped by 12 dB + self.peak_meter_decay_weight = 0.25f64 + .powf((buffer_config.sample_rate as f64 * PEAK_METER_DECAY_MS / 1000.0).recip()) + as f32; + + true + } + + fn process( + &mut self, + buffer: &mut Buffer, + _aux: &mut AuxiliaryBuffers, + _context: &mut impl ProcessContext, + ) -> ProcessStatus { + for channel_samples in buffer.iter_samples() { + let mut amplitude = 0.0; + let num_samples = channel_samples.len(); + + let gain = self.params.gain.smoothed.next(); + for sample in channel_samples { + *sample *= gain; + amplitude += *sample; + } + + // To save resources, a plugin can (and probably should!) only perform expensive + // calculations that are only displayed on the GUI while the GUI is open + if self.params.editor_state.is_open() { + amplitude = (amplitude / num_samples as f32).abs(); + let current_peak_meter = self.peak_meter.load(std::sync::atomic::Ordering::Relaxed); + let new_peak_meter = if amplitude > current_peak_meter { + amplitude + } else { + current_peak_meter * self.peak_meter_decay_weight + + amplitude * (1.0 - self.peak_meter_decay_weight) + }; + + self.peak_meter + .store(new_peak_meter, std::sync::atomic::Ordering::Relaxed) + } + } + + ProcessStatus::Normal + } +} + +impl ClapPlugin for MyPlugin { + const CLAP_ID: &'static str = "com.moist-plugins-gmbh.byo-gui-wgpu"; + const CLAP_DESCRIPTION: Option<&'static str> = + Some("A simple example plugin with a raw WGPU context for rendering"); + const CLAP_MANUAL_URL: Option<&'static str> = Some(Self::URL); + const CLAP_SUPPORT_URL: Option<&'static str> = None; + const CLAP_FEATURES: &'static [ClapFeature] = &[ + ClapFeature::AudioEffect, + ClapFeature::Stereo, + ClapFeature::Mono, + ClapFeature::Utility, + ]; +} + +impl Vst3Plugin for MyPlugin { + const VST3_CLASS_ID: [u8; 16] = *b"ByoGuiWGPUWooooo"; + const VST3_SUBCATEGORIES: &'static [Vst3SubCategory] = + &[Vst3SubCategory::Fx, Vst3SubCategory::Tools]; +} + +nih_export_clap!(MyPlugin); +nih_export_vst3!(MyPlugin); diff --git a/plugins/examples/byo_gui_wgpu/src/main.rs b/plugins/examples/byo_gui_wgpu/src/main.rs new file mode 100644 index 000000000..9d551f5ee --- /dev/null +++ b/plugins/examples/byo_gui_wgpu/src/main.rs @@ -0,0 +1,7 @@ +use nih_plug::prelude::*; + +use byo_gui_wgpu::MyPlugin; + +fn main() { + nih_export_standalone::(); +} From 89fb51248d7386de220c8ff3cfb4553beb475526 Mon Sep 17 00:00:00 2001 From: Billy Messenger <60663878+BillyDM@users.noreply.github.com> Date: Sat, 14 Dec 2024 17:26:57 -0600 Subject: [PATCH 2/7] fix typo in docs --- plugins/examples/byo_gui_gl/src/lib.rs | 2 +- plugins/examples/byo_gui_softbuffer/src/lib.rs | 2 +- plugins/examples/byo_gui_wgpu/src/lib.rs | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/plugins/examples/byo_gui_gl/src/lib.rs b/plugins/examples/byo_gui_gl/src/lib.rs index 5f1eb9328..73596bfb8 100644 --- a/plugins/examples/byo_gui_gl/src/lib.rs +++ b/plugins/examples/byo_gui_gl/src/lib.rs @@ -325,7 +325,7 @@ impl Editor for CustomGlEditor { } } -/// The window handle used for [`EguiEditor`]. +/// The window handle used for [`CustomGlEditor`]. struct CustomGlEditorHandle { state: Arc, window: WindowHandle, diff --git a/plugins/examples/byo_gui_softbuffer/src/lib.rs b/plugins/examples/byo_gui_softbuffer/src/lib.rs index 2d65108d6..3054168bb 100644 --- a/plugins/examples/byo_gui_softbuffer/src/lib.rs +++ b/plugins/examples/byo_gui_softbuffer/src/lib.rs @@ -249,7 +249,7 @@ impl Editor for CustomSoftbufferEditor { } } -/// The window handle used for [`EguiEditor`]. +/// The window handle used for [`CustomSoftbufferEditor`]. struct CustomSoftbufferEditorHandle { state: Arc, window: WindowHandle, diff --git a/plugins/examples/byo_gui_wgpu/src/lib.rs b/plugins/examples/byo_gui_wgpu/src/lib.rs index 0c5333237..c324c36bc 100644 --- a/plugins/examples/byo_gui_wgpu/src/lib.rs +++ b/plugins/examples/byo_gui_wgpu/src/lib.rs @@ -368,7 +368,7 @@ impl Editor for CustomWgpuEditor { } } -/// The window handle used for [`EguiEditor`]. +/// The window handle used for [`CustomWgpuEditor`]. struct CustomWgpuEditorHandle { state: Arc, window: WindowHandle, From 490e7b5ed8f860489f101e3a6d8929463519239c Mon Sep 17 00:00:00 2001 From: Billy Messenger <60663878+BillyDM@users.noreply.github.com> Date: Sat, 14 Dec 2024 17:42:28 -0600 Subject: [PATCH 3/7] work around rust-analyzer derp --- plugins/examples/byo_gui_softbuffer/Cargo.toml | 4 +++- plugins/examples/byo_gui_softbuffer/src/lib.rs | 4 ++++ plugins/examples/byo_gui_wgpu/Cargo.toml | 4 +++- plugins/examples/byo_gui_wgpu/src/lib.rs | 4 ++++ 4 files changed, 14 insertions(+), 2 deletions(-) diff --git a/plugins/examples/byo_gui_softbuffer/Cargo.toml b/plugins/examples/byo_gui_softbuffer/Cargo.toml index 4fa27ea14..6e0bbbc24 100644 --- a/plugins/examples/byo_gui_softbuffer/Cargo.toml +++ b/plugins/examples/byo_gui_softbuffer/Cargo.toml @@ -13,7 +13,9 @@ crate-type = ["cdylib", "lib"] [dependencies] nih_plug = { path = "../../../", features = ["assert_process_allocs", "standalone"] } -baseview = { git = "https://github.com/RustAudio/baseview.git", rev = "9a0b42c09d712777b2edb4c5e0cb6baf21e988f0" } +# NOTE: OpenGL support is not needed here, but rust-analyzer gets confused when +# some crates do use it and others don't +baseview = { git = "https://github.com/RustAudio/baseview.git", rev = "9a0b42c09d712777b2edb4c5e0cb6baf21e988f0", features = ["opengl"]} softbuffer = { version = "0.4.6", default-features = false, features = ["kms", "x11"]} raw-window-handle = "0.5" raw-window-handle-06 = { package = "raw-window-handle", version = "0.6" } diff --git a/plugins/examples/byo_gui_softbuffer/src/lib.rs b/plugins/examples/byo_gui_softbuffer/src/lib.rs index 3054168bb..b02f0976e 100644 --- a/plugins/examples/byo_gui_softbuffer/src/lib.rs +++ b/plugins/examples/byo_gui_softbuffer/src/lib.rs @@ -202,6 +202,10 @@ impl Editor for CustomSoftbufferEditor { scale: scaling_factor .map(|factor| WindowScalePolicy::ScaleFactor(factor as f64)) .unwrap_or(WindowScalePolicy::SystemScaleFactor), + + // NOTE: The OpenGL feature in baseview is not needed here, but rust-analyzer gets + // confused when some crates do use it and others don't. + gl_config: None, }, move |window: &mut baseview::Window<'_>| -> CustomSoftbufferWindow { CustomSoftbufferWindow::new( diff --git a/plugins/examples/byo_gui_wgpu/Cargo.toml b/plugins/examples/byo_gui_wgpu/Cargo.toml index 1cd58bf91..4520114a4 100644 --- a/plugins/examples/byo_gui_wgpu/Cargo.toml +++ b/plugins/examples/byo_gui_wgpu/Cargo.toml @@ -13,7 +13,9 @@ crate-type = ["cdylib", "lib"] [dependencies] nih_plug = { path = "../../../", features = ["assert_process_allocs", "standalone"] } -baseview = { git = "https://github.com/RustAudio/baseview.git", rev = "9a0b42c09d712777b2edb4c5e0cb6baf21e988f0" } +# NOTE: OpenGL support is not needed here, but rust-analyzer gets confused when +# some crates do use it and others don't +baseview = { git = "https://github.com/RustAudio/baseview.git", rev = "9a0b42c09d712777b2edb4c5e0cb6baf21e988f0", features = ["opengl"]} wgpu = "23" raw-window-handle = "0.5" raw-window-handle-06 = { package = "raw-window-handle", version = "0.6" } diff --git a/plugins/examples/byo_gui_wgpu/src/lib.rs b/plugins/examples/byo_gui_wgpu/src/lib.rs index c324c36bc..2bf83ceae 100644 --- a/plugins/examples/byo_gui_wgpu/src/lib.rs +++ b/plugins/examples/byo_gui_wgpu/src/lib.rs @@ -321,6 +321,10 @@ impl Editor for CustomWgpuEditor { scale: scaling_factor .map(|factor| WindowScalePolicy::ScaleFactor(factor as f64)) .unwrap_or(WindowScalePolicy::SystemScaleFactor), + + // NOTE: The OpenGL feature in baseview is not needed here, but rust-analyzer gets + // confused when some crates do use it and others don't. + gl_config: None, }, move |window: &mut baseview::Window<'_>| -> CustomWgpuWindow { CustomWgpuWindow::new( From ac250420fbfd0ec2572105bcd3b4b74dd216ab6f Mon Sep 17 00:00:00 2001 From: Billy Messenger <60663878+BillyDM@users.noreply.github.com> Date: Wed, 16 Apr 2025 10:33:30 -0500 Subject: [PATCH 4/7] fix raw_window_handle panic in Windows --- plugins/examples/byo_gui_softbuffer/src/lib.rs | 7 ++----- plugins/examples/byo_gui_wgpu/src/lib.rs | 7 ++----- 2 files changed, 4 insertions(+), 10 deletions(-) diff --git a/plugins/examples/byo_gui_softbuffer/src/lib.rs b/plugins/examples/byo_gui_softbuffer/src/lib.rs index b02f0976e..4c6c0e517 100644 --- a/plugins/examples/byo_gui_softbuffer/src/lib.rs +++ b/plugins/examples/byo_gui_softbuffer/src/lib.rs @@ -388,15 +388,12 @@ fn baseview_window_to_surface_target( ) } raw_window_handle::RawWindowHandle::Win32(handle) => { - // will this work? i have no idea! let mut raw_handle = raw_window_handle_06::Win32WindowHandle::new( NonZeroIsize::new(handle.hwnd as isize).unwrap(), ); - raw_handle.hinstance = handle - .hinstance - .is_null() - .then(|| NonZeroIsize::new(handle.hinstance as isize).unwrap()); + raw_handle.hinstance = + raw_handle.hinstance = NonZeroIsize::new(handle.hinstance as isize); raw_window_handle_06::RawWindowHandle::Win32(raw_handle) } diff --git a/plugins/examples/byo_gui_wgpu/src/lib.rs b/plugins/examples/byo_gui_wgpu/src/lib.rs index 2bf83ceae..a509c3aaa 100644 --- a/plugins/examples/byo_gui_wgpu/src/lib.rs +++ b/plugins/examples/byo_gui_wgpu/src/lib.rs @@ -474,15 +474,12 @@ fn baseview_window_to_surface_target(window: &baseview::Window<'_>) -> wgpu::Sur ) } raw_window_handle::RawWindowHandle::Win32(handle) => { - // will this work? i have no idea! let mut raw_handle = raw_window_handle_06::Win32WindowHandle::new( NonZeroIsize::new(handle.hwnd as isize).unwrap(), ); - raw_handle.hinstance = handle - .hinstance - .is_null() - .then(|| NonZeroIsize::new(handle.hinstance as isize).unwrap()); + raw_handle.hinstance = + raw_handle.hinstance = NonZeroIsize::new(handle.hinstance as isize); raw_window_handle_06::RawWindowHandle::Win32(raw_handle) } From c712b044df0f05175f1e2f2f3c3f8fc7d8e3cc3b Mon Sep 17 00:00:00 2001 From: Billy Messenger <60663878+BillyDM@users.noreply.github.com> Date: Wed, 16 Apr 2025 10:36:37 -0500 Subject: [PATCH 5/7] fix typo in code --- plugins/examples/byo_gui_softbuffer/src/lib.rs | 3 +-- plugins/examples/byo_gui_wgpu/src/lib.rs | 3 +-- 2 files changed, 2 insertions(+), 4 deletions(-) diff --git a/plugins/examples/byo_gui_softbuffer/src/lib.rs b/plugins/examples/byo_gui_softbuffer/src/lib.rs index 4c6c0e517..a13e82a62 100644 --- a/plugins/examples/byo_gui_softbuffer/src/lib.rs +++ b/plugins/examples/byo_gui_softbuffer/src/lib.rs @@ -392,8 +392,7 @@ fn baseview_window_to_surface_target( NonZeroIsize::new(handle.hwnd as isize).unwrap(), ); - raw_handle.hinstance = - raw_handle.hinstance = NonZeroIsize::new(handle.hinstance as isize); + raw_handle.hinstance = NonZeroIsize::new(handle.hinstance as isize); raw_window_handle_06::RawWindowHandle::Win32(raw_handle) } diff --git a/plugins/examples/byo_gui_wgpu/src/lib.rs b/plugins/examples/byo_gui_wgpu/src/lib.rs index a509c3aaa..03c611058 100644 --- a/plugins/examples/byo_gui_wgpu/src/lib.rs +++ b/plugins/examples/byo_gui_wgpu/src/lib.rs @@ -478,8 +478,7 @@ fn baseview_window_to_surface_target(window: &baseview::Window<'_>) -> wgpu::Sur NonZeroIsize::new(handle.hwnd as isize).unwrap(), ); - raw_handle.hinstance = - raw_handle.hinstance = NonZeroIsize::new(handle.hinstance as isize); + raw_handle.hinstance = NonZeroIsize::new(handle.hinstance as isize); raw_window_handle_06::RawWindowHandle::Win32(raw_handle) } From c270d7376996e18d38db437badf94fa894fa3c6f Mon Sep 17 00:00:00 2001 From: Billy Messenger <60663878+BillyDM@users.noreply.github.com> Date: Wed, 16 Apr 2025 10:59:31 -0500 Subject: [PATCH 6/7] fix auto merge conflict shenanigans --- Cargo.lock | 249 ++++++++++++++++++++++++++++++++++++++++++----------- 1 file changed, 198 insertions(+), 51 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index bbe3508bb..688f01515 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -333,7 +333,7 @@ version = "0.38.0+1.3.281" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0bb44936d800fea8f016d7f2311c6a4f97aebd5dc86f09906139ec848cf3a46f" dependencies = [ - "libloading 0.8.5", + "libloading 0.8.6", ] [[package]] @@ -744,23 +744,6 @@ dependencies = [ "x11rb 0.13.1", ] -[[package]] -name = "baseview" -version = "0.1.0" -source = "git+https://github.com/RustAudio/baseview.git?rev=9a0b42c09d712777b2edb4c5e0cb6baf21e988f0#9a0b42c09d712777b2edb4c5e0cb6baf21e988f0" -dependencies = [ - "cocoa", - "core-foundation 0.9.4", - "keyboard-types", - "nix 0.22.3", - "objc", - "raw-window-handle 0.5.2", - "uuid", - "winapi", - "x11", - "x11rb 0.13.1", -] - [[package]] name = "bindgen" version = "0.70.1" @@ -779,6 +762,15 @@ dependencies = [ "syn 2.0.98", ] +[[package]] +name = "bit-set" +version = "0.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "08807e080ed7f9d5433fa9b275196cfc35414f66a0c79d864dc51a0d825231a3" +dependencies = [ + "bit-vec", +] + [[package]] name = "bit-vec" version = "0.8.0" @@ -866,6 +858,48 @@ version = "3.17.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1628fb46dfa0b37568d12e5edd512553eccf6a22a78e8bde00bb4aed84d5bdbf" +[[package]] +name = "byo_gui_gl" +version = "0.1.0" +dependencies = [ + "atomic_float", + "baseview 0.1.0 (git+https://github.com/RustAudio/baseview.git?rev=9a0b42c09d712777b2edb4c5e0cb6baf21e988f0)", + "crossbeam", + "glow 0.16.0", + "nih_plug", + "raw-window-handle 0.5.2", + "serde", +] + +[[package]] +name = "byo_gui_softbuffer" +version = "0.1.0" +dependencies = [ + "atomic_float", + "baseview 0.1.0 (git+https://github.com/RustAudio/baseview.git?rev=9a0b42c09d712777b2edb4c5e0cb6baf21e988f0)", + "crossbeam", + "nih_plug", + "raw-window-handle 0.5.2", + "raw-window-handle 0.6.2", + "serde", + "softbuffer", +] + +[[package]] +name = "byo_gui_wgpu" +version = "0.1.0" +dependencies = [ + "atomic_float", + "baseview 0.1.0 (git+https://github.com/RustAudio/baseview.git?rev=9a0b42c09d712777b2edb4c5e0cb6baf21e988f0)", + "crossbeam", + "nih_plug", + "pollster", + "raw-window-handle 0.5.2", + "raw-window-handle 0.6.2", + "serde", + "wgpu", +] + [[package]] name = "bytemuck" version = "1.21.0" @@ -1115,7 +1149,7 @@ dependencies = [ "bitflags 1.3.2", "block", "cocoa-foundation", - "core-foundation", + "core-foundation 0.9.4", "core-graphics 0.22.3", "foreign-types 0.3.2", "libc", @@ -1266,8 +1300,8 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2581bbab3b8ffc6fcbd550bf46c355135d16e9ff2a6ea032ad6b9bf1d7efe4fb" dependencies = [ "bitflags 1.3.2", - "core-foundation", - "core-graphics-types", + "core-foundation 0.9.4", + "core-graphics-types 0.1.3", "foreign-types 0.3.2", "libc", ] @@ -1279,8 +1313,21 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c07782be35f9e1140080c6b96f0d44b739e2278479f64e02fdab4e32dfd8b081" dependencies = [ "bitflags 1.3.2", - "core-foundation", - "core-graphics-types", + "core-foundation 0.9.4", + "core-graphics-types 0.1.3", + "foreign-types 0.5.0", + "libc", +] + +[[package]] +name = "core-graphics" +version = "0.24.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fa95a34622365fa5bbf40b20b75dba8dfa8c94c734aea8ac9a5ca38af14316f1" +dependencies = [ + "bitflags 2.8.0", + "core-foundation 0.10.0", + "core-graphics-types 0.2.0", "foreign-types 0.5.0", "libc", ] @@ -1302,7 +1349,7 @@ version = "0.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3d44a101f213f6c4cdc1853d4b78aef6db6bdfa3468798cc1d9912f4735013eb" dependencies = [ - "bitflags 2.6.0", + "bitflags 2.8.0", "core-foundation 0.10.0", "libc", ] @@ -1313,7 +1360,7 @@ version = "19.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "99d74ada66e07c1cefa18f8abfba765b486f250de2e4a999e5727fc0dd4b4a25" dependencies = [ - "core-foundation", + "core-foundation 0.9.4", "core-graphics 0.22.3", "foreign-types 0.3.2", "libc", @@ -1655,6 +1702,15 @@ dependencies = [ "libloading 0.8.6", ] +[[package]] +name = "document-features" +version = "0.2.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "95249b50c6c185bee49034bcb378a49dc2b5dff0be90ff6616d31d64febab05d" +dependencies = [ + "litrs", +] + [[package]] name = "downcast-rs" version = "1.2.1" @@ -1667,6 +1723,45 @@ version = "0.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f25c0e292a7ca6d6498557ff1df68f32c99850012b6ea401cf8daf771f22ff53" +[[package]] +name = "drm" +version = "0.12.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "98888c4bbd601524c11a7ed63f814b8825f420514f78e96f752c437ae9cbb5d1" +dependencies = [ + "bitflags 2.8.0", + "bytemuck", + "drm-ffi", + "drm-fourcc", + "rustix 0.38.44", +] + +[[package]] +name = "drm-ffi" +version = "0.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "97c98727e48b7ccb4f4aea8cfe881e5b07f702d17b7875991881b41af7278d53" +dependencies = [ + "drm-sys", + "rustix 0.38.44", +] + +[[package]] +name = "drm-fourcc" +version = "2.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0aafbcdb8afc29c1a7ee5fbe53b5d62f4565b35a042a662ca9fecd0b54dae6f4" + +[[package]] +name = "drm-sys" +version = "0.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fd39dde40b6e196c2e8763f23d119ddb1a8714534bf7d77fa97a65b0feda3986" +dependencies = [ + "libc", + "linux-raw-sys 0.6.5", +] + [[package]] name = "dtoa" version = "1.0.9" @@ -2003,7 +2098,7 @@ checksum = "46c9a156ec38864999bc9c4156e5f3b50224d4a5578028a64e5a3875caa9ee28" dependencies = [ "bitflags 1.3.2", "byteorder", - "core-foundation", + "core-foundation 0.9.4", "core-graphics 0.22.3", "core-text", "dirs-next", @@ -2408,6 +2503,18 @@ dependencies = [ "web-sys", ] +[[package]] +name = "glow" +version = "0.14.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d51fa363f025f5c111e03f13eda21162faeacb6911fe8caa0c0349f9cf0c4483" +dependencies = [ + "js-sys", + "slotmap", + "wasm-bindgen", + "web-sys", +] + [[package]] name = "glow" version = "0.16.0" @@ -2559,7 +2666,7 @@ version = "0.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "fbcd2dba93594b227a1f57ee09b8b9da8892c34d55aa332e034a228d0fe6a171" dependencies = [ - "bitflags 2.6.0", + "bitflags 2.8.0", "gpu-alloc-types", ] @@ -2569,7 +2676,7 @@ version = "0.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "98ff03b468aa837d70984d55f5d3f846f6ec31fe34bbb97c4f85219caeee1ca4" dependencies = [ - "bitflags 2.6.0", + "bitflags 2.8.0", ] [[package]] @@ -2580,7 +2687,7 @@ checksum = "c151a2a5ef800297b4e79efa4f4bec035c5f51d5ae587287c9b952bdf734cacd" dependencies = [ "log", "presser", - "thiserror", + "thiserror 1.0.69", "windows 0.58.0", ] @@ -2590,9 +2697,9 @@ version = "0.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9c08c1f623a8d0b722b8b99f821eb0ba672a1618f0d3b16ddbee1cedd2dd8557" dependencies = [ - "bitflags 2.6.0", + "bitflags 2.8.0", "gpu-descriptor-types", - "hashbrown", + "hashbrown 0.14.5", ] [[package]] @@ -2601,7 +2708,17 @@ version = "0.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "fdf242682df893b86f33a73828fb09ca4b2d3bb6cc95249707fc684d27484b91" dependencies = [ - "bitflags 2.6.0", + "bitflags 2.8.0", +] + +[[package]] +name = "hashbrown" +version = "0.14.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e5274423e17b7c9fc20b6e7e208532f9b19825d82dfd615708b70edd83df41f1" +dependencies = [ + "ahash", + "allocator-api2", ] [[package]] @@ -2790,7 +2907,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8c9c992b02b5b4c94ea26e32fe5bccb7aa7d9f390ab5c1221ff895bc7ea8b652" dependencies = [ "equivalent", - "hashbrown", + "hashbrown 0.15.2", ] [[package]] @@ -2959,7 +3076,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6aae1df220ece3c0ada96b8153459b67eebe9ae9212258bb0134ae60416fdf76" dependencies = [ "libc", - "libloading 0.8.5", + "libloading 0.8.6", "pkg-config", ] @@ -3051,6 +3168,18 @@ version = "0.4.15" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d26c52dbd32dccf2d10cac7725f8eae5296885fb5703b261f7d0a0739ec807ab" +[[package]] +name = "linux-raw-sys" +version = "0.6.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2a385b1be4e5c3e362ad2ffa73c392e53f031eaa5b7d648e64cd87f27f6063d7" + +[[package]] +name = "litrs" +version = "0.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b4ce301924b7887e9d637144fdade93f9dfff9b60981d4ac161db09720d39aa5" + [[package]] name = "lock_api" version = "0.4.12" @@ -3214,7 +3343,7 @@ version = "0.29.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7ecfd3296f8c56b7c1f6fbac3c71cefa9d78ce009850c45000015f206dc7fa21" dependencies = [ - "bitflags 2.6.0", + "bitflags 2.8.0", "block", "core-graphics-types 0.1.3", "foreign-types 0.5.0", @@ -3297,7 +3426,7 @@ checksum = "3d5941e45a15b53aad4375eedf02033adb7a28931eedc31117faffa52e6a857e" dependencies = [ "arrayvec 0.7.6", "bit-set", - "bitflags 2.6.0", + "bitflags 2.8.0", "cfg_aliases 0.1.1", "codespan-reporting", "hexf-parse", @@ -3306,7 +3435,7 @@ dependencies = [ "rustc-hash 1.1.0", "spirv", "termcolor", - "thiserror", + "thiserror 1.0.69", "unicode-xid", ] @@ -4706,6 +4835,12 @@ version = "0.8.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2b15c43186be67a4fd63bee50d0303afffcef381492ebe2c5d87f324e1b8815c" +[[package]] +name = "renderdoc-sys" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "19b30a45b0cd0bcca8037f3d0dc3421eaf95327a17cad11964fb8179b4fc4832" + [[package]] name = "rgb" version = "0.8.50" @@ -5154,7 +5289,7 @@ dependencies = [ "cfg_aliases 0.2.1", "core-graphics 0.24.0", "drm", - "fastrand 2.1.0", + "fastrand 2.3.0", "foreign-types 0.5.0", "js-sys", "log", @@ -5162,8 +5297,8 @@ dependencies = [ "objc2-foundation", "objc2-quartz-core", "raw-window-handle 0.6.2", - "redox_syscall 0.5.3", - "rustix 0.38.34", + "redox_syscall 0.5.9", + "rustix 0.38.44", "tiny-xlib", "wasm-bindgen", "web-sys", @@ -5191,7 +5326,7 @@ version = "0.3.0+sdk-1.3.268.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "eda41003dc44290527a59b13432d4a0379379fa074b70174882adfbdfd917844" dependencies = [ - "bitflags 2.6.0", + "bitflags 2.8.0", ] [[package]] @@ -5670,6 +5805,18 @@ version = "1.12.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f6ccf251212114b54433ec949fd6a7841275f9ada20dddd2f29e9ceea4501493" +[[package]] +name = "unicode-width" +version = "0.1.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7dd6e30e90baa6f72411720665d41d89b9a3d039dc45b8faea1ddd07f617f6af" + +[[package]] +name = "unicode-xid" +version = "0.2.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ebc1c04c71510c7f702b52b7c350734c9ff1295c464a03335b00bb84fc54f853" + [[package]] name = "utf8parse" version = "0.2.2" @@ -6119,7 +6266,7 @@ checksum = "d63c3c478de8e7e01786479919c8769f62a22eec16788d8c2ac77ce2c132778a" dependencies = [ "arrayvec 0.7.6", "bit-vec", - "bitflags 2.6.0", + "bitflags 2.8.0", "cfg_aliases 0.1.1", "document-features", "indexmap", @@ -6131,7 +6278,7 @@ dependencies = [ "raw-window-handle 0.6.2", "rustc-hash 1.1.0", "smallvec", - "thiserror", + "thiserror 1.0.69", "wgpu-hal", "wgpu-types", ] @@ -6146,7 +6293,7 @@ dependencies = [ "arrayvec 0.7.6", "ash", "bit-set", - "bitflags 2.6.0", + "bitflags 2.8.0", "block", "bytemuck", "cfg_aliases 0.1.1", @@ -6159,7 +6306,7 @@ dependencies = [ "js-sys", "khronos-egl", "libc", - "libloading 0.8.5", + "libloading 0.8.6", "log", "metal", "naga", @@ -6173,7 +6320,7 @@ dependencies = [ "renderdoc-sys", "rustc-hash 1.1.0", "smallvec", - "thiserror", + "thiserror 1.0.69", "wasm-bindgen", "web-sys", "wgpu-types", @@ -6187,7 +6334,7 @@ version = "23.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "610f6ff27778148c31093f3b03abc4840f9636d58d597ca2f5977433acfe0068" dependencies = [ - "bitflags 2.6.0", + "bitflags 2.8.0", "js-sys", "web-sys", ] @@ -6344,7 +6491,7 @@ checksum = "2bbd5b46c938e506ecbce286b6628a02171d56153ba733b6c741fc627ec9579b" dependencies = [ "proc-macro2", "quote", - "syn 2.0.90", + "syn 2.0.98", ] [[package]] @@ -6366,7 +6513,7 @@ checksum = "053c4c462dc91d3b1504c6fe5a726dd15e216ba718e84a0e46a88fbe5ded3515" dependencies = [ "proc-macro2", "quote", - "syn 2.0.90", + "syn 2.0.98", ] [[package]] @@ -6635,7 +6782,7 @@ dependencies = [ "android-activity 0.4.3", "bitflags 1.3.2", "cfg_aliases 0.1.1", - "core-foundation", + "core-foundation 0.9.4", "core-graphics 0.22.3", "dispatch", "instant", @@ -6670,7 +6817,7 @@ dependencies = [ "calloop", "cfg_aliases 0.2.1", "concurrent-queue", - "core-foundation", + "core-foundation 0.9.4", "core-graphics 0.23.2", "cursor-icon", "dpi", From 653f6f8451a76a3e644e3103963f353e2d9d64f7 Mon Sep 17 00:00:00 2001 From: Billy Messenger <60663878+BillyDM@users.noreply.github.com> Date: Wed, 16 Apr 2025 11:04:21 -0500 Subject: [PATCH 7/7] bump wgpu version in byo_gui_wgpu --- Cargo.lock | 271 +++++++++++++++-------- plugins/examples/byo_gui_wgpu/Cargo.toml | 2 +- plugins/examples/byo_gui_wgpu/src/lib.rs | 4 +- 3 files changed, 186 insertions(+), 91 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 688f01515..81c28648b 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -154,7 +154,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ed7572b7ba83a31e20d1b48970ee402d2e3e0537dcfe0a3ff4d6eb7508617d43" dependencies = [ "alsa-sys", - "bitflags 2.8.0", + "bitflags 2.9.0", "cfg-if", "libc", ] @@ -194,7 +194,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ef6978589202a00cd7e118380c448a08b6ed394c3a8df3a430d0898e3a42d046" dependencies = [ "android-properties", - "bitflags 2.8.0", + "bitflags 2.9.0", "cc", "cesu8", "jni", @@ -750,7 +750,7 @@ version = "0.70.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f49d8fed880d473ea71efb9bf597651e77201bdd4893efe54c9e5d65ae04ce6f" dependencies = [ - "bitflags 2.8.0", + "bitflags 2.9.0", "cexpr", "clang-sys", "itertools", @@ -785,9 +785,12 @@ checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a" [[package]] name = "bitflags" -version = "2.8.0" +version = "2.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8f68f53c83ab957f72c32642f3868eec03eb974d1fb82e453128456482613d36" +checksum = "5c8214115b7bf84099f1309324e63141d4c5d7cc26862f97a0a857dbefe165bd" +dependencies = [ + "serde", +] [[package]] name = "block" @@ -902,9 +905,9 @@ dependencies = [ [[package]] name = "bytemuck" -version = "1.21.0" +version = "1.22.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ef657dfab802224e671f5818e9a4935f9b1957ed18e58292690cc39e7a4092a3" +checksum = "b6b1fc10dbac614ebc03540c9dbd60e83887fda27794998c6528f1782047d540" dependencies = [ "bytemuck_derive", ] @@ -944,7 +947,7 @@ version = "0.13.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b99da2f8558ca23c71f4fd15dc57c906239752dd27ff3c00a1d56b685b7cbfec" dependencies = [ - "bitflags 2.8.0", + "bitflags 2.9.0", "log", "polling 3.7.4", "rustix 0.38.44", @@ -1172,10 +1175,11 @@ dependencies = [ [[package]] name = "codespan-reporting" -version = "0.11.1" +version = "0.12.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3538270d33cc669650c4b093848450d380def10c331d38c768e34cac80576e6e" +checksum = "fe6d2e5af09e8c8ad56c969f2157a3d4238cebc7c55f0a517728c38f7b200f81" dependencies = [ + "serde", "termcolor", "unicode-width", ] @@ -1325,7 +1329,7 @@ version = "0.24.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "fa95a34622365fa5bbf40b20b75dba8dfa8c94c734aea8ac9a5ca38af14316f1" dependencies = [ - "bitflags 2.8.0", + "bitflags 2.9.0", "core-foundation 0.10.0", "core-graphics-types 0.2.0", "foreign-types 0.5.0", @@ -1349,7 +1353,7 @@ version = "0.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3d44a101f213f6c4cdc1853d4b78aef6db6bdfa3468798cc1d9912f4735013eb" dependencies = [ - "bitflags 2.8.0", + "bitflags 2.9.0", "core-foundation 0.10.0", "libc", ] @@ -1538,6 +1542,12 @@ dependencies = [ "realfft", ] +[[package]] +name = "crunchy" +version = "0.2.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "43da5946c66ffcc7745f48db692ffbb10a83bfe0afd96235c5c2a4fb23994929" + [[package]] name = "crypto-common" version = "0.1.6" @@ -1729,7 +1739,7 @@ version = "0.12.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "98888c4bbd601524c11a7ed63f814b8825f420514f78e96f752c437ae9cbb5d1" dependencies = [ - "bitflags 2.8.0", + "bitflags 2.9.0", "bytemuck", "drm-ffi", "drm-fourcc", @@ -1806,7 +1816,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7d2768eaa6d5c80a6e2a008da1f0e062dff3c83eb2b28605ea2d0732d46e74d6" dependencies = [ "ahash", - "bitflags 2.8.0", + "bitflags 2.9.0", "emath", "epaint", "nohash-hasher", @@ -2010,7 +2020,7 @@ version = "0.7.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5a3a2d0ff0df09856a5c1c89cc83863a1f0f994c55452186621bb57a01f270b3" dependencies = [ - "bitflags 2.8.0", + "bitflags 2.9.0", "fnv", "generational-arena", "glow 0.12.3", @@ -2090,6 +2100,12 @@ version = "1.0.7" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3f9eec918d3f24069decb9af1554cad7c880e2da24a9afd88aca000531ab82c1" +[[package]] +name = "foldhash" +version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d9c4f5dac5e15c24eb999c26181a6ca40b39fe946cbe4c263c7209467bc83af2" + [[package]] name = "font-kit" version = "0.10.1" @@ -2503,18 +2519,6 @@ dependencies = [ "web-sys", ] -[[package]] -name = "glow" -version = "0.14.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d51fa363f025f5c111e03f13eda21162faeacb6911fe8caa0c0349f9cf0c4483" -dependencies = [ - "js-sys", - "slotmap", - "wasm-bindgen", - "web-sys", -] - [[package]] name = "glow" version = "0.16.0" @@ -2619,7 +2623,7 @@ checksum = "0060f4ed4ef64a5876d9836d7d6c9ed43a463f3ca431682bec1c326064c8c93e" dependencies = [ "glyph_brush_draw_cache", "glyph_brush_layout", - "ordered-float", + "ordered-float 5.0.0", "rustc-hash 2.1.1", "twox-hash 2.1.0", ] @@ -2666,7 +2670,7 @@ version = "0.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "fbcd2dba93594b227a1f57ee09b8b9da8892c34d55aa332e034a228d0fe6a171" dependencies = [ - "bitflags 2.8.0", + "bitflags 2.9.0", "gpu-alloc-types", ] @@ -2676,7 +2680,7 @@ version = "0.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "98ff03b468aa837d70984d55f5d3f846f6ec31fe34bbb97c4f85219caeee1ca4" dependencies = [ - "bitflags 2.8.0", + "bitflags 2.9.0", ] [[package]] @@ -2697,7 +2701,7 @@ version = "0.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9c08c1f623a8d0b722b8b99f821eb0ba672a1618f0d3b16ddbee1cedd2dd8557" dependencies = [ - "bitflags 2.8.0", + "bitflags 2.9.0", "gpu-descriptor-types", "hashbrown 0.14.5", ] @@ -2708,7 +2712,18 @@ version = "0.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "fdf242682df893b86f33a73828fb09ca4b2d3bb6cc95249707fc684d27484b91" dependencies = [ - "bitflags 2.8.0", + "bitflags 2.9.0", +] + +[[package]] +name = "half" +version = "2.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "459196ed295495a68f7d7fe1d84f6c4b7ff0e21fe3017b2f283c6fac3ad803c9" +dependencies = [ + "cfg-if", + "crunchy", + "num-traits", ] [[package]] @@ -2726,6 +2741,9 @@ name = "hashbrown" version = "0.15.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "bf151400ff0baff5465007dd2f3e717f3fe502074ca563069ce3a6629d07b289" +dependencies = [ + "foldhash", +] [[package]] name = "heck" @@ -3145,7 +3163,7 @@ version = "0.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c0ff37bd590ca25063e35af745c343cb7a0271906fb7b37e4813e8f79f00268d" dependencies = [ - "bitflags 2.8.0", + "bitflags 2.9.0", "libc", "redox_syscall 0.5.9", ] @@ -3339,11 +3357,11 @@ dependencies = [ [[package]] name = "metal" -version = "0.29.0" +version = "0.31.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7ecfd3296f8c56b7c1f6fbac3c71cefa9d78ce009850c45000015f206dc7fa21" +checksum = "f569fb946490b5743ad69813cb19629130ce9374034abe31614a36402d18f99e" dependencies = [ - "bitflags 2.8.0", + "bitflags 2.9.0", "block", "core-graphics-types 0.1.3", "foreign-types 0.5.0", @@ -3420,23 +3438,27 @@ dependencies = [ [[package]] name = "naga" -version = "23.0.0" +version = "25.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3d5941e45a15b53aad4375eedf02033adb7a28931eedc31117faffa52e6a857e" +checksum = "2b977c445f26e49757f9aca3631c3b8b836942cb278d69a92e7b80d3b24da632" dependencies = [ "arrayvec 0.7.6", "bit-set", - "bitflags 2.8.0", - "cfg_aliases 0.1.1", + "bitflags 2.9.0", + "cfg_aliases 0.2.1", "codespan-reporting", + "half", + "hashbrown 0.15.2", "hexf-parse", "indexmap", "log", + "num-traits", + "once_cell", "rustc-hash 1.1.0", "spirv", - "termcolor", - "thiserror 1.0.69", - "unicode-xid", + "strum", + "thiserror 2.0.11", + "unicode-ident", ] [[package]] @@ -3459,7 +3481,7 @@ version = "0.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2076a31b7010b17a38c01907c45b945e8f11495ee4dd588309718901b1f7a5b7" dependencies = [ - "bitflags 2.8.0", + "bitflags 2.9.0", "jni-sys", "log", "ndk-sys 0.5.0+25.2.9519653", @@ -3473,7 +3495,7 @@ version = "0.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c3f42e7bbe13d351b6bead8286a43aac9534b82bd3cc43e47037f012ebfd62d4" dependencies = [ - "bitflags 2.8.0", + "bitflags 2.9.0", "jni-sys", "log", "ndk-sys 0.6.0+11769913", @@ -3728,6 +3750,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "071dfc062690e90b734c0b2273ce72ad0ffa95f0c74596bc250dcfd960262841" dependencies = [ "autocfg", + "libm", ] [[package]] @@ -3871,7 +3894,7 @@ version = "0.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e4e89ad9e3d7d297152b17d39ed92cd50ca8063a89a9fa569046d41568891eff" dependencies = [ - "bitflags 2.8.0", + "bitflags 2.9.0", "block2 0.5.1", "libc", "objc2 0.5.2", @@ -3887,7 +3910,7 @@ version = "0.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "74dd3b56391c7a0596a295029734d3c1c5e7e510a4cb30245f8221ccea96b009" dependencies = [ - "bitflags 2.8.0", + "bitflags 2.9.0", "block2 0.5.1", "objc2 0.5.2", "objc2-core-location", @@ -3911,7 +3934,7 @@ version = "0.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "617fbf49e071c178c0b24c080767db52958f716d9eabdf0890523aeae54773ef" dependencies = [ - "bitflags 2.8.0", + "bitflags 2.9.0", "block2 0.5.1", "objc2 0.5.2", "objc2-foundation", @@ -3962,7 +3985,7 @@ version = "0.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0ee638a5da3799329310ad4cfa62fbf045d5f56e3ef5ba4149e7452dcf89d5a8" dependencies = [ - "bitflags 2.8.0", + "bitflags 2.9.0", "block2 0.5.1", "dispatch", "libc", @@ -3987,7 +4010,7 @@ version = "0.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "dd0cba1276f6023976a406a14ffa85e1fdd19df6b0f737b063b95f6c8c7aadd6" dependencies = [ - "bitflags 2.8.0", + "bitflags 2.9.0", "block2 0.5.1", "objc2 0.5.2", "objc2-foundation", @@ -3999,7 +4022,7 @@ version = "0.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e42bee7bff906b14b167da2bac5efe6b6a07e6f7c0a21a7308d40c960242dc7a" dependencies = [ - "bitflags 2.8.0", + "bitflags 2.9.0", "block2 0.5.1", "objc2 0.5.2", "objc2-foundation", @@ -4022,7 +4045,7 @@ version = "0.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b8bb46798b20cd6b91cbd113524c490f1686f4c4e8f49502431415f3512e2b6f" dependencies = [ - "bitflags 2.8.0", + "bitflags 2.9.0", "block2 0.5.1", "objc2 0.5.2", "objc2-cloud-kit", @@ -4054,7 +4077,7 @@ version = "0.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "76cfcbf642358e8689af64cee815d139339f3ed8ad05103ed5eaf73db8d84cb3" dependencies = [ - "bitflags 2.8.0", + "bitflags 2.9.0", "block2 0.5.1", "objc2 0.5.2", "objc2-core-location", @@ -4104,9 +4127,9 @@ dependencies = [ [[package]] name = "once_cell" -version = "1.20.3" +version = "1.21.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "945462a4b81e43c4e3ba96bd7b49d834c6f61198356aa858733bc4acf3cbe62e" +checksum = "42f5e15c9953c5e4ccceeb2e7382a716482c34515315f7b03532b8b4e8393d2d" [[package]] name = "open" @@ -4138,6 +4161,15 @@ dependencies = [ "libredox", ] +[[package]] +name = "ordered-float" +version = "4.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7bb71e1b3fa6ca1c61f383464aaf2bb0e2f8e772a1f01d486832464de363b951" +dependencies = [ + "num-traits", +] + [[package]] name = "ordered-float" version = "5.0.0" @@ -4477,6 +4509,12 @@ dependencies = [ "rand_pcg 0.3.1", ] +[[package]] +name = "portable-atomic" +version = "1.11.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "350e9b48cbc6b0e028b0473b114454c6316e57336ee184ceab6e53f72c178b3e" + [[package]] name = "powerfmt" version = "0.2.0" @@ -4783,7 +4821,7 @@ version = "0.5.9" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "82b568323e98e49e2a0899dcee453dd679fae22d69adf9b11dd508d1549b7e2f" dependencies = [ - "bitflags 2.8.0", + "bitflags 2.9.0", ] [[package]] @@ -4921,7 +4959,7 @@ version = "0.38.44" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "fdb5bc1ae2baa591800df16c9ca78619bf65c0488b41b96ccec5d11220d8c154" dependencies = [ - "bitflags 2.8.0", + "bitflags 2.9.0", "errno", "libc", "linux-raw-sys 0.4.15", @@ -5326,7 +5364,7 @@ version = "0.3.0+sdk-1.3.268.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "eda41003dc44290527a59b13432d4a0379379fa074b70174882adfbdfd917844" dependencies = [ - "bitflags 2.8.0", + "bitflags 2.9.0", ] [[package]] @@ -5355,6 +5393,28 @@ version = "0.11.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7da8b5736845d9f2fcb837ea5d9e2628564b3b043a70948a3f0b778838c5fb4f" +[[package]] +name = "strum" +version = "0.26.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8fec0f0aef304996cf250b31b5a10dee7980c85da9d759361292b8bca5a18f06" +dependencies = [ + "strum_macros", +] + +[[package]] +name = "strum_macros" +version = "0.26.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4c6bee85a5a24955dc440386795aa378cd9cf82acd5f764469152d2270e581be" +dependencies = [ + "heck", + "proc-macro2", + "quote", + "rustversion", + "syn 2.0.98", +] + [[package]] name = "swash" version = "0.1.19" @@ -5811,12 +5871,6 @@ version = "0.1.14" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7dd6e30e90baa6f72411720665d41d89b9a3d039dc45b8faea1ddd07f617f6af" -[[package]] -name = "unicode-xid" -version = "0.2.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ebc1c04c71510c7f702b52b7c350734c9ff1295c464a03335b00bb84fc54f853" - [[package]] name = "utf8parse" version = "0.2.2" @@ -5874,7 +5928,7 @@ version = "0.1.0" source = "git+https://github.com/robbert-vdh/vizia.git?tag=patched-2024-05-06#e3fab5530cda9cb90f679508d9f058bd62189d36" dependencies = [ "accesskit", - "bitflags 2.8.0", + "bitflags 2.9.0", "chrono", "copypasta 0.8.2", "cosmic-text", @@ -5938,7 +5992,7 @@ name = "vizia_style" version = "0.1.0" source = "git+https://github.com/robbert-vdh/vizia.git?tag=patched-2024-05-06#e3fab5530cda9cb90f679508d9f058bd62189d36" dependencies = [ - "bitflags 2.8.0", + "bitflags 2.9.0", "cssparser", "femtovg", "morphorm", @@ -6235,17 +6289,20 @@ dependencies = [ [[package]] name = "wgpu" -version = "23.0.1" +version = "25.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "80f70000db37c469ea9d67defdc13024ddf9a5f1b89cb2941b812ad7cde1735a" +checksum = "ca6049eb2014a0e0d8689f9b787605dd71d5bbfdc74095ead499f3cff705c229" dependencies = [ "arrayvec 0.7.6", - "cfg_aliases 0.1.1", + "bitflags 2.9.0", + "cfg_aliases 0.2.1", "document-features", + "hashbrown 0.15.2", "js-sys", "log", "naga", "parking_lot 0.12.3", + "portable-atomic", "profiling", "raw-window-handle 0.6.2", "smallvec", @@ -6260,49 +6317,84 @@ dependencies = [ [[package]] name = "wgpu-core" -version = "23.0.1" +version = "25.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d63c3c478de8e7e01786479919c8769f62a22eec16788d8c2ac77ce2c132778a" +checksum = "a19813e647da7aa3cdaa84f5846e2c64114970ea7c86b1e6aae8be08091f4bdc" dependencies = [ "arrayvec 0.7.6", + "bit-set", "bit-vec", - "bitflags 2.8.0", - "cfg_aliases 0.1.1", + "bitflags 2.9.0", + "cfg_aliases 0.2.1", "document-features", + "hashbrown 0.15.2", "indexmap", "log", "naga", "once_cell", "parking_lot 0.12.3", + "portable-atomic", "profiling", "raw-window-handle 0.6.2", "rustc-hash 1.1.0", "smallvec", - "thiserror 1.0.69", + "thiserror 2.0.11", + "wgpu-core-deps-apple", + "wgpu-core-deps-emscripten", + "wgpu-core-deps-windows-linux-android", "wgpu-hal", "wgpu-types", ] +[[package]] +name = "wgpu-core-deps-apple" +version = "25.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cfd488b3239b6b7b185c3b045c39ca6bf8af34467a4c5de4e0b1a564135d093d" +dependencies = [ + "wgpu-hal", +] + +[[package]] +name = "wgpu-core-deps-emscripten" +version = "25.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f09ad7aceb3818e52539acc679f049d3475775586f3f4e311c30165cf2c00445" +dependencies = [ + "wgpu-hal", +] + +[[package]] +name = "wgpu-core-deps-windows-linux-android" +version = "25.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cba5fb5f7f9c98baa7c889d444f63ace25574833df56f5b817985f641af58e46" +dependencies = [ + "wgpu-hal", +] + [[package]] name = "wgpu-hal" -version = "23.0.1" +version = "25.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "89364b8a0b211adc7b16aeaf1bd5ad4a919c1154b44c9ce27838213ba05fd821" +checksum = "fb7c4a1dc42ff14c23c9b11ebf1ee85cde661a9b1cf0392f79c1faca5bc559fb" dependencies = [ "android_system_properties", "arrayvec 0.7.6", "ash", "bit-set", - "bitflags 2.8.0", + "bitflags 2.9.0", "block", "bytemuck", - "cfg_aliases 0.1.1", + "cfg-if", + "cfg_aliases 0.2.1", "core-graphics-types 0.1.3", - "glow 0.14.2", + "glow 0.16.0", "glutin_wgl_sys 0.6.0", "gpu-alloc", "gpu-allocator", "gpu-descriptor", + "hashbrown 0.15.2", "js-sys", "khronos-egl", "libc", @@ -6312,15 +6404,15 @@ dependencies = [ "naga", "ndk-sys 0.5.0+25.2.9519653", "objc", - "once_cell", + "ordered-float 4.6.0", "parking_lot 0.12.3", + "portable-atomic", "profiling", "range-alloc", "raw-window-handle 0.6.2", "renderdoc-sys", - "rustc-hash 1.1.0", "smallvec", - "thiserror 1.0.69", + "thiserror 2.0.11", "wasm-bindgen", "web-sys", "wgpu-types", @@ -6330,12 +6422,15 @@ dependencies = [ [[package]] name = "wgpu-types" -version = "23.0.0" +version = "25.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "610f6ff27778148c31093f3b03abc4840f9636d58d597ca2f5977433acfe0068" +checksum = "2aa49460c2a8ee8edba3fca54325540d904dd85b2e086ada762767e17d06e8bc" dependencies = [ - "bitflags 2.8.0", + "bitflags 2.9.0", + "bytemuck", "js-sys", + "log", + "thiserror 2.0.11", "web-sys", ] @@ -6811,7 +6906,7 @@ checksum = "a809eacf18c8eca8b6635091543f02a5a06ddf3dad846398795460e6e0ae3cc0" dependencies = [ "android-activity 0.6.0", "atomic-waker", - "bitflags 2.8.0", + "bitflags 2.9.0", "block2 0.5.1", "bytemuck", "calloop", @@ -6880,7 +6975,7 @@ version = "0.33.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3268f3d866458b787f390cf61f4bbb563b922d091359f9608842999eaee3943c" dependencies = [ - "bitflags 2.8.0", + "bitflags 2.9.0", ] [[package]] @@ -7035,7 +7130,7 @@ version = "0.4.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d039de8032a9a8856a6be89cea3e5d12fdd82306ab7c94d74e6deab2460651c5" dependencies = [ - "bitflags 2.8.0", + "bitflags 2.9.0", "dlib", "log", "once_cell", diff --git a/plugins/examples/byo_gui_wgpu/Cargo.toml b/plugins/examples/byo_gui_wgpu/Cargo.toml index 4520114a4..205f244c0 100644 --- a/plugins/examples/byo_gui_wgpu/Cargo.toml +++ b/plugins/examples/byo_gui_wgpu/Cargo.toml @@ -16,7 +16,7 @@ nih_plug = { path = "../../../", features = ["assert_process_allocs", "standalon # NOTE: OpenGL support is not needed here, but rust-analyzer gets confused when # some crates do use it and others don't baseview = { git = "https://github.com/RustAudio/baseview.git", rev = "9a0b42c09d712777b2edb4c5e0cb6baf21e988f0", features = ["opengl"]} -wgpu = "23" +wgpu = "25" raw-window-handle = "0.5" raw-window-handle-06 = { package = "raw-window-handle", version = "0.6" } pollster = "0.4.0" diff --git a/plugins/examples/byo_gui_wgpu/src/lib.rs b/plugins/examples/byo_gui_wgpu/src/lib.rs index 03c611058..937ed8285 100644 --- a/plugins/examples/byo_gui_wgpu/src/lib.rs +++ b/plugins/examples/byo_gui_wgpu/src/lib.rs @@ -65,7 +65,7 @@ impl CustomWgpuWindow { let width = (unscaled_width as f64 * scaling_factor as f64).round() as u32; let height = (unscaled_height as f64 * scaling_factor as f64).round() as u32; - let instance = wgpu::Instance::new(wgpu::InstanceDescriptor::default()); + let instance = wgpu::Instance::new(&wgpu::InstanceDescriptor::default()); let surface = unsafe { instance.create_surface_unsafe(target) }.unwrap(); @@ -88,8 +88,8 @@ impl CustomWgpuWindow { required_limits: wgpu::Limits::downlevel_webgl2_defaults() .using_resolution(adapter.limits()), memory_hints: wgpu::MemoryHints::MemoryUsage, + ..Default::default() }, - None, ) .await .expect("Failed to create device");