From 64e82a211e3bb60291d45cc6ddbf158dfe1e45f8 Mon Sep 17 00:00:00 2001 From: chillfish8 Date: Sat, 3 Oct 2026 22:48:08 +0100 Subject: [PATCH 01/12] Add regression test fixtures --- Cargo.lock | 2 + av-denoise/Cargo.toml | 4 + av-denoise/tests/fixtures/parity.txt | 383 +++++++++++++++++++++++++++ av-denoise/tests/parity/clips.rs | 56 ++++ av-denoise/tests/parity/configs.rs | 204 ++++++++++++++ av-denoise/tests/parity/fixture.rs | 98 +++++++ av-denoise/tests/parity/main.rs | 104 ++++++++ 7 files changed, 851 insertions(+) create mode 100644 av-denoise/tests/fixtures/parity.txt create mode 100644 av-denoise/tests/parity/clips.rs create mode 100644 av-denoise/tests/parity/configs.rs create mode 100644 av-denoise/tests/parity/fixture.rs create mode 100644 av-denoise/tests/parity/main.rs diff --git a/Cargo.lock b/Cargo.lock index d516805..ffd708f 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -190,6 +190,7 @@ dependencies = [ "bytesize", "clap", "crossbeam-channel", + "cubecl", "ffms2-sys", "indicatif", "mimalloc", @@ -200,6 +201,7 @@ dependencies = [ "tracing-indicatif", "tracing-subscriber", "v_frame", + "wgpu", "y4m", ] diff --git a/av-denoise/Cargo.toml b/av-denoise/Cargo.toml index 1755532..7ab7250 100644 --- a/av-denoise/Cargo.toml +++ b/av-denoise/Cargo.toml @@ -56,6 +56,10 @@ indicatif = { version = "0.18", optional = true, default-features = false } tracing-indicatif = { version = "0.3", optional = true } tracing-subscriber = { version = "0.3", optional = true, features = ["env-filter"] } +[dev-dependencies] +cubecl.workspace = true +wgpu = "29" + [build-dependencies] pkg-config = { version = "0.3.34", optional = true } diff --git a/av-denoise/tests/fixtures/parity.txt b/av-denoise/tests/fixtures/parity.txt new file mode 100644 index 0000000..0ecad29 --- /dev/null +++ b/av-denoise/tests/fixtures/parity.txt @@ -0,0 +1,383 @@ +# adapters: AMD Radeon AI PRO R9700 (RADV GFX1201)|radv|Mesa 26.2.2-arch3.2; AMD Radeon AI PRO R9700 (RADV GFX1201)|radv|Mesa 26.2.2-arch3.2; AMD Ryzen 9 9950X 16-Core Processor (RADV RAPHAEL_MENDOCINO)|radv|Mesa 26.2.2-arch3.2 +nl4d_chroma_10 f0.u 161f5b580e5064dd +nl4d_chroma_10 f0.v adb1904c0b9328ad +nl4d_chroma_10 f0.y 11cc4683a0611f99 +nl4d_chroma_10 f1.u b6bc81c1fd1b76c6 +nl4d_chroma_10 f1.v 81fd9ae313e869bf +nl4d_chroma_10 f1.y 6314ed1c36536d09 +nl4d_chroma_10 f10.u d639b63f54ba446b +nl4d_chroma_10 f10.v c6eef6f8cdc530fa +nl4d_chroma_10 f10.y f4dfaad0a380a7e3 +nl4d_chroma_10 f11.u 1e4e184845cec46b +nl4d_chroma_10 f11.v b777d39c49928832 +nl4d_chroma_10 f11.y 060b898058902cdb +nl4d_chroma_10 f2.u 892e38df5acf117c +nl4d_chroma_10 f2.v 48bfe26b7067e1c6 +nl4d_chroma_10 f2.y 586dac4893bb0b5e +nl4d_chroma_10 f3.u 7d6b84fca3d88fc3 +nl4d_chroma_10 f3.v f3648a7728998344 +nl4d_chroma_10 f3.y 8fcba87f5350cf5f +nl4d_chroma_10 f4.u 5ac068c597a36295 +nl4d_chroma_10 f4.v 3b0a83f09e65ea97 +nl4d_chroma_10 f4.y f41ce69ba683fe34 +nl4d_chroma_10 f5.u 80276fb5dffbac0d +nl4d_chroma_10 f5.v f11ed94bd284009c +nl4d_chroma_10 f5.y b33c4217a2a5567c +nl4d_chroma_10 f6.u 2809beb330d8bd0b +nl4d_chroma_10 f6.v 5308179884af107d +nl4d_chroma_10 f6.y f95163970c4a3e42 +nl4d_chroma_10 f7.u 759ecf183a5e888b +nl4d_chroma_10 f7.v 9de3eb0b738acb1e +nl4d_chroma_10 f7.y e6e619a8fbfc4f74 +nl4d_chroma_10 f8.u df5b506de4bae36d +nl4d_chroma_10 f8.v 22c6d1c96831b818 +nl4d_chroma_10 f8.y df7b3b736ff10a2e +nl4d_chroma_10 f9.u 628fd606b926170e +nl4d_chroma_10 f9.v 83cb1401d0dbf987 +nl4d_chroma_10 f9.y 8a2dac912021485b +nl4d_grain_8 f0.u de3a29958a0cfdee +nl4d_grain_8 f0.v e06919110df6aaf8 +nl4d_grain_8 f0.y 3a91ab99fe317322 +nl4d_grain_8 f1.u 56c2b42b5e3ba76e +nl4d_grain_8 f1.v 21bc3e02b9454632 +nl4d_grain_8 f1.y c0be61fd7efa1a16 +nl4d_grain_8 f10.u c35b9c01d13ff06f +nl4d_grain_8 f10.v 00154a8154a2a331 +nl4d_grain_8 f10.y ff92d6ba20092197 +nl4d_grain_8 f11.u 63ad2397626689c9 +nl4d_grain_8 f11.v 9fe1a2d3acdf7357 +nl4d_grain_8 f11.y 07aa59f519bf235b +nl4d_grain_8 f2.u aa48d2b79a5ac418 +nl4d_grain_8 f2.v 153ee290cdf20dfb +nl4d_grain_8 f2.y cd361ce5085a5753 +nl4d_grain_8 f3.u 7d28bce3b73ed591 +nl4d_grain_8 f3.v e7e89de054de038a +nl4d_grain_8 f3.y 7fd336e1f6483583 +nl4d_grain_8 f4.u 7c2eb1ec251768d4 +nl4d_grain_8 f4.v f1fcc4442b36dc57 +nl4d_grain_8 f4.y 46b294be5f075502 +nl4d_grain_8 f5.u a5bcebb6b3e397ed +nl4d_grain_8 f5.v f85f6833a2f52f67 +nl4d_grain_8 f5.y 3e83b20dd67d84d2 +nl4d_grain_8 f6.u fccd90249eca907f +nl4d_grain_8 f6.v 1a7358cf1f6b0497 +nl4d_grain_8 f6.y 5c79d91832a4f020 +nl4d_grain_8 f7.u 99191803fddb2ffc +nl4d_grain_8 f7.v 2c253716e5210740 +nl4d_grain_8 f7.y 9a175b94728f8631 +nl4d_grain_8 f8.u 76720368694b9dda +nl4d_grain_8 f8.v d1fc3836b5ad3c64 +nl4d_grain_8 f8.y 96ab849789b00c0e +nl4d_grain_8 f9.u 31699de899f8a1f6 +nl4d_grain_8 f9.v a3080004132f2010 +nl4d_grain_8 f9.y dec85fdcf53748e6 +nl4d_grain_8 grain cfe6c57268d13d4f +nl4d_luma_8 f0.u de3a29958a0cfdee +nl4d_luma_8 f0.v e06919110df6aaf8 +nl4d_luma_8 f0.y 3a91ab99fe317322 +nl4d_luma_8 f1.u 56c2b42b5e3ba76e +nl4d_luma_8 f1.v 21bc3e02b9454632 +nl4d_luma_8 f1.y c0be61fd7efa1a16 +nl4d_luma_8 f10.u c35b9c01d13ff06f +nl4d_luma_8 f10.v 00154a8154a2a331 +nl4d_luma_8 f10.y ff92d6ba20092197 +nl4d_luma_8 f11.u 63ad2397626689c9 +nl4d_luma_8 f11.v 9fe1a2d3acdf7357 +nl4d_luma_8 f11.y 07aa59f519bf235b +nl4d_luma_8 f2.u aa48d2b79a5ac418 +nl4d_luma_8 f2.v 153ee290cdf20dfb +nl4d_luma_8 f2.y cd361ce5085a5753 +nl4d_luma_8 f3.u 7d28bce3b73ed591 +nl4d_luma_8 f3.v e7e89de054de038a +nl4d_luma_8 f3.y 7fd336e1f6483583 +nl4d_luma_8 f4.u 7c2eb1ec251768d4 +nl4d_luma_8 f4.v f1fcc4442b36dc57 +nl4d_luma_8 f4.y 46b294be5f075502 +nl4d_luma_8 f5.u a5bcebb6b3e397ed +nl4d_luma_8 f5.v f85f6833a2f52f67 +nl4d_luma_8 f5.y 3e83b20dd67d84d2 +nl4d_luma_8 f6.u fccd90249eca907f +nl4d_luma_8 f6.v 1a7358cf1f6b0497 +nl4d_luma_8 f6.y 5c79d91832a4f020 +nl4d_luma_8 f7.u 99191803fddb2ffc +nl4d_luma_8 f7.v 2c253716e5210740 +nl4d_luma_8 f7.y 9a175b94728f8631 +nl4d_luma_8 f8.u 76720368694b9dda +nl4d_luma_8 f8.v d1fc3836b5ad3c64 +nl4d_luma_8 f8.y 96ab849789b00c0e +nl4d_luma_8 f9.u 31699de899f8a1f6 +nl4d_luma_8 f9.v a3080004132f2010 +nl4d_luma_8 f9.y dec85fdcf53748e6 +nl4d_lumachroma_10 f0.u 161f5b580e5064dd +nl4d_lumachroma_10 f0.v adb1904c0b9328ad +nl4d_lumachroma_10 f0.y 85405eca45bceebf +nl4d_lumachroma_10 f1.u b6bc81c1fd1b76c6 +nl4d_lumachroma_10 f1.v 81fd9ae313e869bf +nl4d_lumachroma_10 f1.y dced2157e6b329cb +nl4d_lumachroma_10 f10.u d639b63f54ba446b +nl4d_lumachroma_10 f10.v c6eef6f8cdc530fa +nl4d_lumachroma_10 f10.y 494b16347a0ae43e +nl4d_lumachroma_10 f11.u 1e4e184845cec46b +nl4d_lumachroma_10 f11.v b777d39c49928832 +nl4d_lumachroma_10 f11.y 4c5e34cf02d74d32 +nl4d_lumachroma_10 f2.u 892e38df5acf117c +nl4d_lumachroma_10 f2.v 48bfe26b7067e1c6 +nl4d_lumachroma_10 f2.y 1fb402cbd5b25f54 +nl4d_lumachroma_10 f3.u 7d6b84fca3d88fc3 +nl4d_lumachroma_10 f3.v f3648a7728998344 +nl4d_lumachroma_10 f3.y 31e4694b95ebd8df +nl4d_lumachroma_10 f4.u 5ac068c597a36295 +nl4d_lumachroma_10 f4.v 3b0a83f09e65ea97 +nl4d_lumachroma_10 f4.y 6c0cb4387420c742 +nl4d_lumachroma_10 f5.u 80276fb5dffbac0d +nl4d_lumachroma_10 f5.v f11ed94bd284009c +nl4d_lumachroma_10 f5.y 99e5ee0e991e62a3 +nl4d_lumachroma_10 f6.u 2809beb330d8bd0b +nl4d_lumachroma_10 f6.v 5308179884af107d +nl4d_lumachroma_10 f6.y 43e53e07d2e1e767 +nl4d_lumachroma_10 f7.u 759ecf183a5e888b +nl4d_lumachroma_10 f7.v 9de3eb0b738acb1e +nl4d_lumachroma_10 f7.y a06857772a909dd9 +nl4d_lumachroma_10 f8.u df5b506de4bae36d +nl4d_lumachroma_10 f8.v 22c6d1c96831b818 +nl4d_lumachroma_10 f8.y 4d90b3731f3d012e +nl4d_lumachroma_10 f9.u 628fd606b926170e +nl4d_lumachroma_10 f9.v 83cb1401d0dbf987 +nl4d_lumachroma_10 f9.y 76f67fb89ac73f9e +nl4d_reseed_8 f0.u a7a8985a94219195 +nl4d_reseed_8 f0.v a6ba3cab66a1e14e +nl4d_reseed_8 f0.y 8bbd866b5e366bde +nl4d_reseed_8 f1.u 490aab2f8de9432f +nl4d_reseed_8 f1.v 388329719d64308b +nl4d_reseed_8 f1.y 8dbdced79806242c +nl4d_reseed_8 f10.u 3c544d4c5c5e0466 +nl4d_reseed_8 f10.v b884225f1f4f4014 +nl4d_reseed_8 f10.y 83c019c921163a96 +nl4d_reseed_8 f11.u 34f0a9dbdfb2dd65 +nl4d_reseed_8 f11.v dd98fa5a0490bd91 +nl4d_reseed_8 f11.y 40edf847a8356b20 +nl4d_reseed_8 f2.u 96814423f16645e0 +nl4d_reseed_8 f2.v 028ca41cf77399ae +nl4d_reseed_8 f2.y 78c5dcd96ad51433 +nl4d_reseed_8 f3.u 5f47139ddfa8fd51 +nl4d_reseed_8 f3.v 71a028f4ba8242e6 +nl4d_reseed_8 f3.y 4e54d1c85b8a496f +nl4d_reseed_8 f4.u 2cc80c12eef33583 +nl4d_reseed_8 f4.v 8a38e8cae02f28be +nl4d_reseed_8 f4.y a6a418d5ec33631a +nl4d_reseed_8 f5.u fc70d7ff20bb8613 +nl4d_reseed_8 f5.v 59a431607b2d5a3b +nl4d_reseed_8 f5.y e6d031ad55009594 +nl4d_reseed_8 f6.u 1ec35b96284e672d +nl4d_reseed_8 f6.v ef76521cc139512d +nl4d_reseed_8 f6.y 68775ea2469988bb +nl4d_reseed_8 f7.u 53c46090ad950f0e +nl4d_reseed_8 f7.v 2d482d3d3ce38c75 +nl4d_reseed_8 f7.y a3e1b13d1e8932d3 +nl4d_reseed_8 f8.u 30720e9c31605ac8 +nl4d_reseed_8 f8.v 33d60bd12ea0fcc1 +nl4d_reseed_8 f8.y c848ba40cc59342f +nl4d_reseed_8 f9.u e4e83c24a5c1ed93 +nl4d_reseed_8 f9.v 464e4fc8b9db8559 +nl4d_reseed_8 f9.y 1f72af395684b2d2 +nl4d_reseed_8 reseed.u fc70d7ff20bb8613 +nl4d_reseed_8 reseed.v 59a431607b2d5a3b +nl4d_reseed_8 reseed.y e6d031ad55009594 +nl4d_short_8 f0.u de3a29958a0cfdee +nl4d_short_8 f0.v e06919110df6aaf8 +nl4d_short_8 f0.y a88df6ca31fce47d +nl4d_short_8 f1.u 56c2b42b5e3ba76e +nl4d_short_8 f1.v 21bc3e02b9454632 +nl4d_short_8 f1.y 86ce99c97794c164 +nl4d_short_8 f2.u aa48d2b79a5ac418 +nl4d_short_8 f2.v 153ee290cdf20dfb +nl4d_short_8 f2.y 144fbe62f6663f5e +nl4d_yuv_8 f0.u b877cf9c924be2ee +nl4d_yuv_8 f0.v 97fcc69c38d153d8 +nl4d_yuv_8 f0.y e034fe39b18571a6 +nl4d_yuv_8 f1.u 84c2e194f3f06fd6 +nl4d_yuv_8 f1.v 673319d76e8e6866 +nl4d_yuv_8 f1.y e17a75dc27502ff9 +nl4d_yuv_8 f10.u ef4b41583f16a75f +nl4d_yuv_8 f10.v 5c69fbf8c61a30e4 +nl4d_yuv_8 f10.y 0fca5ca8a9d95cd8 +nl4d_yuv_8 f11.u 93d9f8d0d17cfa21 +nl4d_yuv_8 f11.v 9238766e56b03100 +nl4d_yuv_8 f11.y 4b6062220072ba83 +nl4d_yuv_8 f2.u f4c0e5cbf398ba99 +nl4d_yuv_8 f2.v 4d502d607e8e82e1 +nl4d_yuv_8 f2.y 547a96d5f4a4b5e0 +nl4d_yuv_8 f3.u 1394c61ca4f39cbb +nl4d_yuv_8 f3.v 3ddcf4cfbf8aeb64 +nl4d_yuv_8 f3.y 9dd1c7a91a4b3873 +nl4d_yuv_8 f4.u b905ec5d1f3a2bf7 +nl4d_yuv_8 f4.v 60a5e4facd97c9ea +nl4d_yuv_8 f4.y c16d07d842105902 +nl4d_yuv_8 f5.u 35ff99dbf3619bd2 +nl4d_yuv_8 f5.v ec6f050fe64921f4 +nl4d_yuv_8 f5.y 7131076a689de95e +nl4d_yuv_8 f6.u e789300d31ff8d6e +nl4d_yuv_8 f6.v f3c045b93eae731a +nl4d_yuv_8 f6.y 9a7aa069be7e901f +nl4d_yuv_8 f7.u ee2d1bd9f3929862 +nl4d_yuv_8 f7.v e24246e3ee863c98 +nl4d_yuv_8 f7.y 04690bbd76f45ea6 +nl4d_yuv_8 f8.u 0d884bda5d1f3439 +nl4d_yuv_8 f8.v bac2240ca0518c14 +nl4d_yuv_8 f8.y a3cea1562490cac4 +nl4d_yuv_8 f9.u 0fa9087726a56dcb +nl4d_yuv_8 f9.v 10fc1181945814c1 +nl4d_yuv_8 f9.y 210fe7c99806f7e6 +nlm_fast_spatial_8 f0.u 4617b7de6002d675 +nlm_fast_spatial_8 f0.v b6a491ada7b1c0d4 +nlm_fast_spatial_8 f0.y 5576512fe4885820 +nlm_fast_spatial_8 f1.u 724f90b6044216b7 +nlm_fast_spatial_8 f1.v 0ba069a1487ec38f +nlm_fast_spatial_8 f1.y b1c39b8fdfc8e1f5 +nlm_fast_spatial_8 f2.u fc8cfe52fedd0875 +nlm_fast_spatial_8 f2.v e76290349add76e5 +nlm_fast_spatial_8 f2.y d9276d4dd9ca3760 +nlm_fast_spatial_8 f3.u 1718a5d78eefa2fc +nlm_fast_spatial_8 f3.v 66584f27ad6aff9d +nlm_fast_spatial_8 f3.y 6426a45c9448164a +nlm_fast_spatial_8 f4.u 33f6baef6090221f +nlm_fast_spatial_8 f4.v d60e7b685b2ffe29 +nlm_fast_spatial_8 f4.y cfffef291d7fc390 +nlm_fast_spatial_8 f5.u d88118a851062faf +nlm_fast_spatial_8 f5.v 0b3d22b81b2f57c4 +nlm_fast_spatial_8 f5.y 14e4cc9c282972d7 +nlm_fast_temporal_8 f0.u de3a29958a0cfdee +nlm_fast_temporal_8 f0.v e06919110df6aaf8 +nlm_fast_temporal_8 f0.y fcb26120eb5d94db +nlm_fast_temporal_8 f1.u fd62c278ce48fa70 +nlm_fast_temporal_8 f1.v c18c4b057d07f972 +nlm_fast_temporal_8 f1.y d779ac64aa959b10 +nlm_fast_temporal_8 f2.u 90d97a80ce199581 +nlm_fast_temporal_8 f2.v 7a4d6aa2b4d2ea6d +nlm_fast_temporal_8 f2.y f8b56f929264b910 +nlm_fast_temporal_8 f3.u eada4ac4effff9d1 +nlm_fast_temporal_8 f3.v 32de1fc4111b0a6f +nlm_fast_temporal_8 f3.y 6753f1fb81a84ae3 +nlm_fast_temporal_8 f4.u a75076e37736553d +nlm_fast_temporal_8 f4.v 0069ec52ab66fd3c +nlm_fast_temporal_8 f4.y b8c1a06c065769f7 +nlm_fast_temporal_8 f5.u 352d8ab8c3cd0f9d +nlm_fast_temporal_8 f5.v e6ab0ab322a449ad +nlm_fast_temporal_8 f5.y 25007fc91c11d289 +nlm_fast_temporal_8 f6.u d0aa912deafc17ae +nlm_fast_temporal_8 f6.v 23b1bb13fa24c92f +nlm_fast_temporal_8 f6.y 32978b4b98581379 +nlm_fast_temporal_8 f7.u 94cd33fec9855e38 +nlm_fast_temporal_8 f7.v a703b87e3f207542 +nlm_fast_temporal_8 f7.y 80ece6d9cdb674de +nlm_fast_temporal_8 f8.u c3d29e4b003342a6 +nlm_fast_temporal_8 f8.v 80f8d3d551b5624a +nlm_fast_temporal_8 f8.y a0cdacda49786ee5 +nlm_fast_temporal_8 f9.u 31699de899f8a1f6 +nlm_fast_temporal_8 f9.v a3080004132f2010 +nlm_fast_temporal_8 f9.y c90fd0fd2a204614 +nlm_hq_reseed_8 f0.u 04753832ff160c19 +nlm_hq_reseed_8 f0.v c4cdcd5f252d9180 +nlm_hq_reseed_8 f0.y c199cdf4b6d63943 +nlm_hq_reseed_8 f1.u c1f7b4e11b04975b +nlm_hq_reseed_8 f1.v e47d574c6ea6337e +nlm_hq_reseed_8 f1.y 60a4598b837cdda0 +nlm_hq_reseed_8 f10.u cf9ab4585f69d1e6 +nlm_hq_reseed_8 f10.v cc72471bc094d40a +nlm_hq_reseed_8 f10.y c3e01289efd5ee85 +nlm_hq_reseed_8 f11.u 9fea58fe56eedb22 +nlm_hq_reseed_8 f11.v 048f6872f3a8139b +nlm_hq_reseed_8 f11.y 5bcef01b2a68b941 +nlm_hq_reseed_8 f2.u a111b54fa94204ad +nlm_hq_reseed_8 f2.v ff5a79bea66348c8 +nlm_hq_reseed_8 f2.y 3857fa203c1b56d5 +nlm_hq_reseed_8 f3.u 048567c2e213b3ae +nlm_hq_reseed_8 f3.v 3cff0cf2af268acf +nlm_hq_reseed_8 f3.y f24929570c0a5c42 +nlm_hq_reseed_8 f4.u 4e6e862eec5e45f1 +nlm_hq_reseed_8 f4.v a06e57a303351550 +nlm_hq_reseed_8 f4.y 05aa09ffc7de5ac2 +nlm_hq_reseed_8 f5.u 57b8a591bde2dda2 +nlm_hq_reseed_8 f5.v 98012faf98f1ea85 +nlm_hq_reseed_8 f5.y e9db1c6a8f13683f +nlm_hq_reseed_8 f6.u 1c8209e74c683edb +nlm_hq_reseed_8 f6.v 0da09d2d0446d498 +nlm_hq_reseed_8 f6.y 1c7b1711d7da120c +nlm_hq_reseed_8 f7.u 38a2d4331d256efc +nlm_hq_reseed_8 f7.v 92a589cd380f3385 +nlm_hq_reseed_8 f7.y 7614ae699a520d71 +nlm_hq_reseed_8 f8.u 3949798131611062 +nlm_hq_reseed_8 f8.v ce53158d3f27eee1 +nlm_hq_reseed_8 f8.y bda3e0c7f5ba36e6 +nlm_hq_reseed_8 f9.u be730d32af5ce9b9 +nlm_hq_reseed_8 f9.v 060f4becf320d8b5 +nlm_hq_reseed_8 f9.y 2932a9f48ef1da7a +nlm_hq_reseed_8 reseed.u ee5a033eff1cec62 +nlm_hq_reseed_8 reseed.v 091466ca4c54dd44 +nlm_hq_reseed_8 reseed.y c1191ab5bcb8b59a +nlm_hq_short_8 f0.u de3a29958a0cfdee +nlm_hq_short_8 f0.v e06919110df6aaf8 +nlm_hq_short_8 f0.y 18173befc5c8a643 +nlm_hq_short_8 f1.u 56c2b42b5e3ba76e +nlm_hq_short_8 f1.v 21bc3e02b9454632 +nlm_hq_short_8 f1.y 92fca4a0c774d537 +nlm_hq_temporal_10 f0.u 32d98959d8b47ef9 +nlm_hq_temporal_10 f0.v efe1ac26c4b48580 +nlm_hq_temporal_10 f0.y 403175fad9ca03bc +nlm_hq_temporal_10 f1.u 02541d255613ac65 +nlm_hq_temporal_10 f1.v 3535b70313d44148 +nlm_hq_temporal_10 f1.y 5e5b049b3aa70e9b +nlm_hq_temporal_10 f2.u 68a2fa57eef9993f +nlm_hq_temporal_10 f2.v 4fd30237b406f7c6 +nlm_hq_temporal_10 f2.y 5f884426f82d6c3d +nlm_hq_temporal_10 f3.u 1037960377095d4e +nlm_hq_temporal_10 f3.v 31cbefd6eea66b89 +nlm_hq_temporal_10 f3.y f220ee7455a8281e +nlm_hq_temporal_10 f4.u 2e29d4c058d324b5 +nlm_hq_temporal_10 f4.v fbd3547ce5e3e8aa +nlm_hq_temporal_10 f4.y 0ad46d104bc93bcf +nlm_hq_temporal_10 f5.u 4452545706606b26 +nlm_hq_temporal_10 f5.v 9e419603e4b4874d +nlm_hq_temporal_10 f5.y 637fee770dd99737 +nlm_hq_temporal_10 f6.u c7ec78d52c88cb3d +nlm_hq_temporal_10 f6.v 2f247ce505843049 +nlm_hq_temporal_10 f6.y 08599c0c5c975af3 +nlm_hq_temporal_10 f7.u f00de96b084ac96d +nlm_hq_temporal_10 f7.v 39b8fb0faf3b24f6 +nlm_hq_temporal_10 f7.y f39a68a6ac679a5e +nlm_hq_temporal_10 f8.u 45cd0f0da37b7402 +nlm_hq_temporal_10 f8.v 41729f2bb18ef3bd +nlm_hq_temporal_10 f8.y 0ff51c2c41ff00e7 +nlm_hq_temporal_10 f9.u 3ab7a1b00a1951a9 +nlm_hq_temporal_10 f9.v 3dbc3defe23b0c27 +nlm_hq_temporal_10 f9.y e10c3015fa8750b6 +nlm_hq_yuv_8 f0.u f970724b17f24e86 +nlm_hq_yuv_8 f0.v 15d15d6b817104fb +nlm_hq_yuv_8 f0.y 4c0f956cc3ba66b7 +nlm_hq_yuv_8 f1.u 3f90a59f584adb7f +nlm_hq_yuv_8 f1.v 271769c2ff81ac00 +nlm_hq_yuv_8 f1.y 8d0c2026167508f7 +nlm_hq_yuv_8 f2.u 2ceb47a4d646a500 +nlm_hq_yuv_8 f2.v 7b5529870e936dc5 +nlm_hq_yuv_8 f2.y 17e33d0daed22553 +nlm_hq_yuv_8 f3.u c6db31e60fd4f0c2 +nlm_hq_yuv_8 f3.v 34d575a3b0b00a6c +nlm_hq_yuv_8 f3.y d179e0244d43d93e +nlm_hq_yuv_8 f4.u 9e4dc2dc78d11d27 +nlm_hq_yuv_8 f4.v 2fe6433a3093ec65 +nlm_hq_yuv_8 f4.y 86a568874c9beff9 +nlm_hq_yuv_8 f5.u 03571ed1600f8e73 +nlm_hq_yuv_8 f5.v fc26a667bfd079fc +nlm_hq_yuv_8 f5.y 1651ff29203647c4 +nlm_hq_yuv_8 f6.u 6227b6335493fde0 +nlm_hq_yuv_8 f6.v cb12d1968b1cdb2d +nlm_hq_yuv_8 f6.y 08f5aab713b6f6b5 +nlm_hq_yuv_8 f7.u 015c5765d390e62c +nlm_hq_yuv_8 f7.v 03b3b7f76910c833 +nlm_hq_yuv_8 f7.y 97d1a658749b6dd4 +nlm_hq_yuv_8 f8.u 3d07fb9423b4358a +nlm_hq_yuv_8 f8.v 8936a47d748a06cc +nlm_hq_yuv_8 f8.y 9dec3321bf7baa7d +nlm_hq_yuv_8 f9.u 21674dce3917607e +nlm_hq_yuv_8 f9.v 153ac3f2416ee668 +nlm_hq_yuv_8 f9.y 911b7a061aa3a328 diff --git a/av-denoise/tests/parity/clips.rs b/av-denoise/tests/parity/clips.rs new file mode 100644 index 0000000..643935e --- /dev/null +++ b/av-denoise/tests/parity/clips.rs @@ -0,0 +1,56 @@ +use av_denoise::{Depth, FrameLayout, Planes}; + +/// A moving sine texture plus hashed noise, so motion search and the noise estimator both have work. +pub fn clip(layout: FrameLayout, frames: usize) -> Vec { + let (chroma_width, chroma_height) = layout.chroma_dims(); + let mut clip = Vec::with_capacity(frames); + + for index in 0..frames { + let y_plane = plane(layout.width, layout.height, layout.depth, index, 0); + let u_plane = plane(chroma_width, chroma_height, layout.depth, index, 1); + let v_plane = plane(chroma_width, chroma_height, layout.depth, index, 2); + clip.push(Planes { + y: y_plane, + u: u_plane, + v: v_plane, + }); + } + + clip +} + +fn plane(width: u32, height: u32, depth: Depth, frame: usize, channel: u32) -> Vec { + let max = depth.max_value(); + let shift = frame as f32 * 1.5; + let mut samples = Vec::with_capacity((width * height) as usize); + + for row in 0..height { + for column in 0..width { + let phase_x = (column as f32 + shift) / width as f32 * std::f32::consts::TAU * 3.0; + let phase_y = row as f32 / height as f32 * std::f32::consts::TAU * 2.0; + let texture = 0.5 + 0.2 * phase_x.sin() * phase_y.cos(); + let noise = hashed_noise(column, row, frame as u32, channel) * 0.03; + let value = (texture + noise).clamp(0.0, 1.0); + let code = (value * max).round() as u16; + samples.push(code); + } + } + + encode(&samples, depth) +} + +fn hashed_noise(column: u32, row: u32, frame: u32, channel: u32) -> f32 { + let mut hash = column.wrapping_mul(0x9E37_79B9) ^ row.wrapping_mul(0x85EB_CA6B); + hash ^= frame.wrapping_mul(0xC2B2_AE35) ^ channel.wrapping_mul(0x27D4_EB2F); + hash ^= hash >> 15; + hash = hash.wrapping_mul(0x2C1B_3C6D); + hash ^= hash >> 12; + hash as f32 / u32::MAX as f32 - 0.5 +} + +fn encode(samples: &[u16], depth: Depth) -> Vec { + match depth.bytes_per_sample() { + 1 => samples.iter().map(|&sample| sample as u8).collect(), + _ => samples.iter().flat_map(|sample| sample.to_le_bytes()).collect(), + } +} diff --git a/av-denoise/tests/parity/configs.rs b/av-denoise/tests/parity/configs.rs new file mode 100644 index 0000000..1187f2c --- /dev/null +++ b/av-denoise/tests/parity/configs.rs @@ -0,0 +1,204 @@ +use av_denoise::accelerate::Accelerator; +use av_denoise::{ + Algorithm, + ChannelIntent, + DenoisingMode, + Depth, + Device, + FrameLayout, + Nl4dOptions, + NlmeansHqOptions, + NlmeansOptions, + PlaneOptions, + Subsampling, +}; + +pub struct ParityConfig { + pub name: &'static str, + pub options: PlaneOptions, + pub layout: FrameLayout, + pub frames: usize, + pub reseed: bool, +} + +const WIDTH: u32 = 160; +const HEIGHT: u32 = 128; + +fn layout(subsampling: Subsampling, depth: Depth) -> FrameLayout { + FrameLayout { + width: WIDTH, + height: HEIGHT, + subsampling, + depth, + } +} + +fn options(intent: ChannelIntent, mode: DenoisingMode, algorithm: Algorithm) -> PlaneOptions { + PlaneOptions { + accelerators: vec![Accelerator::Vulkan], + device: Device::Default, + intent, + mode, + algorithm, + luma_strength: None, + chroma_strength: None, + luma_lambda_ht: None, + chroma_lambda_ht: None, + } +} + +pub fn all() -> Vec { + let temporal = DenoisingMode::Temporal { radius: 2 }; + let fast = Algorithm::Nlmeans(NlmeansOptions::default()); + let hq = Algorithm::NlmeansHq(NlmeansHqOptions::default()); + let nl4d = Algorithm::Nl4d(Nl4dOptions::default()); + let nl4d_grain = Algorithm::Nl4d(Nl4dOptions { + grain_export: true, + ..Nl4dOptions::default() + }); + let nl4d_windowed = Algorithm::Nl4d(Nl4dOptions { + windowed_noise_estimation: true, + ..Nl4dOptions::default() + }); + let yuv420_8 = layout(Subsampling::Yuv420, Depth::Eight); + let yuv420_10 = layout(Subsampling::Yuv420, Depth::Ten); + let yuv444_8 = layout(Subsampling::Yuv444, Depth::Eight); + + vec![ + config( + "nlm_fast_spatial_8", + ChannelIntent::LumaChroma, + DenoisingMode::Spacial, + fast, + yuv420_8, + 6, + false, + ), + config( + "nlm_fast_temporal_8", + ChannelIntent::LumaChroma, + temporal, + fast, + yuv420_8, + 10, + false, + ), + config( + "nlm_hq_temporal_10", + ChannelIntent::LumaChroma, + temporal, + hq, + yuv420_10, + 10, + false, + ), + config( + "nlm_hq_short_8", + ChannelIntent::Luma, + temporal, + hq, + yuv420_8, + 2, + false, + ), + config( + "nlm_hq_yuv_8", + ChannelIntent::YuvFused, + temporal, + hq, + yuv444_8, + 10, + false, + ), + config( + "nl4d_luma_8", + ChannelIntent::Luma, + temporal, + nl4d, + yuv420_8, + 12, + false, + ), + config( + "nl4d_chroma_10", + ChannelIntent::Chroma, + temporal, + nl4d, + yuv420_10, + 12, + false, + ), + config( + "nl4d_lumachroma_10", + ChannelIntent::LumaChroma, + temporal, + nl4d, + yuv420_10, + 12, + false, + ), + config( + "nl4d_yuv_8", + ChannelIntent::YuvFused, + temporal, + nl4d, + yuv444_8, + 12, + false, + ), + config( + "nl4d_short_8", + ChannelIntent::Luma, + temporal, + nl4d, + yuv420_8, + 3, + false, + ), + config( + "nl4d_grain_8", + ChannelIntent::Luma, + temporal, + nl4d_grain, + yuv420_8, + 12, + false, + ), + config( + "nl4d_reseed_8", + ChannelIntent::LumaChroma, + temporal, + nl4d_windowed, + yuv420_8, + 12, + true, + ), + config( + "nlm_hq_reseed_8", + ChannelIntent::LumaChroma, + temporal, + hq, + yuv420_8, + 12, + true, + ), + ] +} + +fn config( + name: &'static str, + intent: ChannelIntent, + mode: DenoisingMode, + algorithm: Algorithm, + layout: FrameLayout, + frames: usize, + reseed: bool, +) -> ParityConfig { + ParityConfig { + name, + options: options(intent, mode, algorithm), + layout, + frames, + reseed, + } +} diff --git a/av-denoise/tests/parity/fixture.rs b/av-denoise/tests/parity/fixture.rs new file mode 100644 index 0000000..c263b7d --- /dev/null +++ b/av-denoise/tests/parity/fixture.rs @@ -0,0 +1,98 @@ +use std::collections::BTreeMap; +use std::path::PathBuf; + +use wgpu::{Adapter, Backends, Instance, InstanceDescriptor}; + +pub type Entries = BTreeMap<(String, String), String>; + +const ADAPTERS_PREFIX: &str = "# adapters: "; + +/// The recorded adapter fingerprint and hashes. +pub struct Fixture { + pub adapters: String, + pub entries: Entries, +} + +/// FNV-1a 64, chosen because its output never changes between Rust releases. +pub fn hash(bytes: &[u8]) -> u64 { + let mut state = 0xcbf2_9ce4_8422_2325u64; + + for &byte in bytes { + state ^= byte as u64; + state = state.wrapping_mul(0x0000_0100_0000_01b3); + } + + state +} + +pub fn path() -> PathBuf { + PathBuf::from(env!("CARGO_MANIFEST_DIR")).join("tests/fixtures/parity.txt") +} + +/// Names and drivers of every Vulkan adapter, sorted and joined with `; `. +pub fn adapter_fingerprint() -> String { + let mut descriptor = InstanceDescriptor::new_without_display_handle(); + descriptor.backends = Backends::VULKAN; + let instance = Instance::new(descriptor); + let enumeration = instance.enumerate_adapters(Backends::VULKAN); + let adapters = cubecl::future::block_on(enumeration); + + let mut described: Vec = adapters.iter().map(describe).collect(); + described.sort(); + described.join("; ") +} + +/// Panics when the recorded adapters differ from this machine's. +pub fn check_adapters(recorded: &str) { + let current = adapter_fingerprint(); + if recorded == current { + return; + } + + panic!( + "parity fixture was recorded on different adapters\n recorded: {recorded}\n current: {current}\n \ + re-record with AVD_PARITY_RECORD=1 on this machine before starting a refactor, never mid-refactor" + ); +} + +/// Lines of `