diff --git a/apps/docs/content/docs/integrations/react-native-skia.mdx b/apps/docs/content/docs/integrations/react-native-skia.mdx index 463408906..b0bc6b1bc 100644 --- a/apps/docs/content/docs/integrations/react-native-skia.mdx +++ b/apps/docs/content/docs/integrations/react-native-skia.mdx @@ -9,7 +9,7 @@ With the default (Ganesh) releases of react-native-skia there is no coupling at Graphite builds of react-native-skia (the `@next` release channel) render through Dawn, the same WebGPU implementation react-native-webgpu is built on, and the two packages are designed to share it: -- **One Dawn copy.** Both packages vendor the exact same prebuilt Dawn artifact, pinned to the Dawn revision of the Skia milestone (for example `dawn-chrome-m150`). When both are installed, react-native-skia detects react-native-webgpu at `pod install` time and defers to its copy, so the process contains exactly one Dawn. A build-time guard compares the two packages' Dawn tags and fails the native build on a mismatch instead of letting two incompatible copies coexist. +- **One Dawn copy.** Both packages vendor the exact same prebuilt Dawn artifact, pinned to the Dawn revision of the Skia milestone (for example `dawn-chrome-m152`). When both are installed, react-native-skia detects react-native-webgpu at `pod install` time and defers to its copy, so the process contains exactly one Dawn. A build-time guard compares the two packages' Dawn tags and fails the native build on a mismatch instead of letting two incompatible copies coexist. - **One `wgpu::Instance`.** When a Graphite build of react-native-skia is present, react-native-webgpu adopts Skia's instance automatically at startup (discovered at runtime, independent of native-module initialization order). Graphite's device and every device you create through `navigator.gpu` live on the same instance. - **The WebGPU API lives here.** Graphite builds of react-native-skia do not install `navigator.gpu` or any WebGPU JS API; react-native-webgpu is the single WebGPU API surface. If you want to write WebGPU code in an app that uses Skia, install react-native-webgpu alongside it. @@ -17,6 +17,19 @@ Graphite builds of react-native-skia (the `@next` release channel) render throug Because a Graphite build links react-native-webgpu's Dawn copy, the two packages must be built against the same Dawn tag; this is what makes sharing an instance and importing devices sound. Releases are kept in lockstep, and the native build fails with an explicit message if the tags ever differ, so a mismatch surfaces at build time rather than as undefined behavior at runtime. Default (Ganesh) releases of react-native-skia have no such constraint. +## Compatibility + +Both packages follow Chrome/Skia milestones: react-native-webgpu pins the Dawn revision from the Skia milestone's `DEPS`, and react-native-skia ships that milestone's binaries as `react-native-skia-graphite-*` `.0.0`. Pick one row and install versions from it. + +| Milestone | react-native-webgpu | Dawn release tag | `@shopify/react-native-skia` (Graphite `@next`) | +| --- | --- | --- | --- | +| m152 | unreleased | `dawn-chrome-m152` | unreleased (Graphite `152.0.0`) | +| m150 | 0.7.0 – 0.8.1 | `dawn-chrome-m150` | 2.9.1-next.1 – 2.11.0-next.2 (Graphite `150.0.0`) | + +react-native-webgpu 0.6.4 and earlier predate the interop APIs (`importDevice` landed in 0.7.0); install them alongside a default (Ganesh) build of react-native-skia only. + +To check what an installed pair is built against, compare `node -p "require('react-native-webgpu/package.json').dawn"` with the `graphiteDependencies` in `@shopify/react-native-skia`'s `package.json`. They have to name the same milestone. + ## Rendering with Skia's device `Skia.getNativeDevice()` returns the raw pointer of Graphite's `wgpu::Device` as a `BigInt`, and [`importDevice()`](/docs/getting-started/native-api#importing-an-external-device) wraps it into a regular `GPUDevice`: diff --git a/apps/example/ios/Podfile.lock b/apps/example/ios/Podfile.lock index 943738687..3008b3bf3 100644 --- a/apps/example/ios/Podfile.lock +++ b/apps/example/ios/Podfile.lock @@ -3037,85 +3037,85 @@ SPEC CHECKSUMS: fmt: 530618a01105dae0fa3a2f27c81ae11fa8f67eac glog: 5683914934d5b6e4240e497e0f4a3b42d1854183 hermes-engine: 35c763d57c9832d0eef764316ca1c4d043581394 - NitroImage: 4ffcf183d975de179ae1662b7c3b4b3b37747c7e - NitroModules: 9ec4a2e0b9af22ba1f1f550e1dd9be94143afd18 - RCT-Folly: b29feb752b08042c62badaef7d453f3bb5e6ae23 + NitroImage: 75df80efc3bebd26e5fbe66a546ca83122773919 + NitroModules: d2c5b374ac227a6a27e2ef95c21c99bc63ea44af + RCT-Folly: 121436bcc4611f6bde5c09bf35f0a7a82cef1969 RCTDeprecation: c0ed3249a97243002615517dff789bf4666cf585 RCTRequired: 58719f5124f9267b5f9649c08bf23d9aea845b23 RCTTypeSafety: 4aefa8328ab1f86da273f08517f1f6b343f6c2cc React: 2073376f47c71b7e9a0af7535986a77522ce1049 React-callinvoker: 751b6f2c83347a0486391c3f266f291f0f53b27e - React-Core: dff5d29973349b11dd6631c9498456d75f846d5e - React-CoreModules: c0ae04452e4c5d30e06f8e94692a49107657f537 - React-cxxreact: 376fd672c95dfb64ad5cc246e6a1e9edb78dec4c + React-Core: 7195661f0b48e7ea46c3360ccb575288a20c932c + React-CoreModules: 14f0054ab46000dd3b816d6528af3bd600d82073 + React-cxxreact: 7f602425c63096c398dac13cd7a300efd7c281ae React-debug: 7b56a0a7da432353287d2eedac727903e35278f5 - React-defaultsnativemodule: 393b81aaa6211408f50a6ef00a277847256dd881 - React-domnativemodule: 5fb5829baa7a7a0f217019cbad1eb226d94f7062 - React-Fabric: a17c4ae35503673b57b91c2d1388429e7cbee452 - React-FabricComponents: a76572ddeba78ebe4ec58615291e9db4a55cd46a - React-FabricImage: d806eb2695d7ef355ec28d1a21f5a14ac26b1cae - React-featureflags: 1690ec3c453920b6308e23a4e24eb9c3632f9c75 - React-featureflagsnativemodule: 7b7e8483fc671c5a33aefd699b7c7a3c0bdfdfec - React-graphics: ea146ee799dc816524a3a0922fc7be0b5a52dcc1 - React-hermes: fcbdc45ecf38259fe3b12642bd0757c52270a107 - React-idlecallbacksnativemodule: a353f9162eaa7ad787e68aba9f52a1cfa8154098 - React-ImageManager: ec5cf55ce9cc81719eb5f1f51d23d04db851c86c - React-jserrorhandler: 594c593f3d60f527be081e2cace7710c2bd9f524 - React-jsi: 59ec3190dd364cca86a58869e7755477d2468948 - React-jsiexecutor: b87d78a2e8dd7a6f56e9cdac038da45de98c944f - React-jsinspector: b9204adf1af622c98e78af96ec1bca615c2ce2bd - React-jsinspectorcdp: 4a356fa69e412d35d3a38c44d4a6cc555c5931e8 - React-jsinspectornetwork: 7820056773178f321cbf18689e1ffcd38276a878 - React-jsinspectortracing: b341c5ef6e031a33e0bd462d67fd397e8e9cd612 - React-jsitooling: 401655e05cb966b0081225c5201d90734a567cb9 - React-jsitracing: 67eff6dea0cb58a1e7bd8b49243012d88c0f511e - React-logger: a3cb5b29c32b8e447b5a96919340e89334062b48 - React-Mapbuffer: 9d2434a42701d6144ca18f0ca1c4507808ca7696 - React-microtasksnativemodule: 75b6604b667d297292345302cc5bfb6b6aeccc1b - react-native-safe-area-context: c00143b4823773bba23f2f19f85663ae89ceb460 - react-native-skia: fc73e9bdc46ebb420a98c9c2be29fee80f565e79 - react-native-webgpu: 77c012dcaf2ba43b77e34c9ea237fab24ff1e0fb - React-NativeModulesApple: 879fbdc5dcff7136abceb7880fe8a2022a1bd7c3 + React-defaultsnativemodule: 695d8a0b40f735edb3c4031e0f049e567fdac47a + React-domnativemodule: 6d66c1f61f277d008d98cae650ce2c025b89d3b9 + React-Fabric: 997d4115d688f483cb409a1290171bff3c93dab4 + React-FabricComponents: 8167e5e363ca3a3fe394d8afee355e4072bea1db + React-FabricImage: f8f9f2c97657116702acc670e3f4357bc842bed3 + React-featureflags: dfb4d0d527d55dd968231370f6832b9197ee653d + React-featureflagsnativemodule: c63cfd8fe95cd98f12ebb37daa919c4544810a45 + React-graphics: fd795f1c2a1133a08dde31725b20949edd545dca + React-hermes: 0a167bbb02c242664745e82154578c64e90a88e5 + React-idlecallbacksnativemodule: 1798c6aa33ddc7c2e9fa3c3d67729728639889e9 + React-ImageManager: c498ee6945dffacc82bfa175aa3264212f27c70b + React-jserrorhandler: 216951fea62fc26c600f4c96f0dc4fd53d1e7a9b + React-jsi: 9c27d27d3007b73c702ad3fd5a6166557c741020 + React-jsiexecutor: 2b24f4ed4026344a27f717bf947a434cbbeeff7a + React-jsinspector: 02394b059c48805780f7d977366317a24168d00e + React-jsinspectorcdp: f4b6d5c5c9db05ef44d082716714f90cfeed96bb + React-jsinspectornetwork: e7c77d01b5f0664e24c0bec1aea27d5e3d7fb746 + React-jsinspectortracing: aaa96a4e53abb88dc6d47da3b5744c710652fef9 + React-jsitooling: 226e5f4147c7b6f1ae1954a8406ffa713f3da828 + React-jsitracing: 8a2fbeaa9c53c3f0b23904ccffefc890eae48d71 + React-logger: 1767babce2d28c3251039ce05556714a2c8c6ded + React-Mapbuffer: 33f678ee25b6c0ee2b01b1ecec08e3e02424cefe + React-microtasksnativemodule: 44b44a4d3cd6ffb85d928abf741acdc26722de2e + react-native-safe-area-context: 54d812805f3c4e08a4580ad086cbde1d8780c2e4 + react-native-skia: 6354d59a2751ef30f1025deb1bf355dd3856963e + react-native-webgpu: 8fed9d0ea5e5b10e0392d4c549cdf0cea86f3c26 + React-NativeModulesApple: b5d18bc109c45c9a1c6b71664991b5cc3adc4e48 React-oscompat: 93b5535ea7f7dff46aaee4f78309a70979bdde9d - React-perflogger: 5536d2df3d18fe0920263466f7b46a56351c0510 - React-performancetimeline: 9041c53efa07f537164dcfe7670a36642352f4c2 + React-perflogger: a03d913e3205b00aee4128082abe42fd45ce0c98 + React-performancetimeline: 9b5986cc15afafb9bf246d7dd55bdd138df94451 React-RCTActionSheet: 42195ae666e6d79b4af2346770f765b7c29435b9 - React-RCTAnimation: fa103ccc3503b1ed8dedca7e62e7823937748843 - React-RCTAppDelegate: 665d4baf19424cef08276e9ac0d8771eec4519f9 - React-RCTBlob: 0fa9530c255644db095f2c4fd8d89738d9d9ecc0 - React-RCTFabric: 1fcd8af6e25f92532f56b4ba092e58662c14d156 - React-RCTFBReactNativeSpec: db171247585774f9f0a30f75109cc51568686213 - React-RCTImage: ba824e61ce2e920a239a65d130b83c3a1d426dff - React-RCTLinking: d2dc199c37e71e6f505d9eca3e5c33be930014d4 - React-RCTNetwork: 87137d4b9bd77e5068f854dd5c1f30d4b072faf6 - React-RCTRuntime: 137fafaa808a8b7e76a510e8be45f9f827899daa - React-RCTSettings: 71f5c7fd7b5f4e725a4e2114a4b4373d0e46048f - React-RCTText: b94d4699b49285bee22b8ebf768924d607eccee3 - React-RCTVibration: 6e3993c4f6c36a3899059f9a9ead560ddaf5a7d7 + React-RCTAnimation: 5c10527683128c56ff2c09297fb080f7c35bd293 + React-RCTAppDelegate: c616bd5b0d12f0b21dfacee9cd2d512c6df013aa + React-RCTBlob: 6e3757bdd7dce6fd9788c0dd675fd6b6c432db9d + React-RCTFabric: e8f3b9da97477710bf0904a62eb5b5209c964694 + React-RCTFBReactNativeSpec: c042f8d60d44ad9e2c722da89323c0bdab7a37af + React-RCTImage: a3482fe1ae562d1bab08b42d4670a7c9a21813cd + React-RCTLinking: d82b9adb141aef9d2b38d446b837ae7017ab60aa + React-RCTNetwork: fa9350dd99354c5695964f589bd4790bdd4f6a85 + React-RCTRuntime: be99a38cd23388c08921d8969c82a1997a11ec90 + React-RCTSettings: b7f4a03f44dba1d3a4dc6770843547b203ca9129 + React-RCTText: 91dc597a5f6b27fd1048bb287c41ea05eeca9333 + React-RCTVibration: 27b09ddf74bddfa30a58d20e48f885ea6ed6c9d9 React-rendererconsistency: b4785e5ed837dc7c242bbc5fdd464b33ef5bfae7 - React-renderercss: e6fb0ba387b389c595ffa86b8b628716d31f58dc - React-rendererdebug: 60a03de5c7ea59bf2d39791eb43c4c0f5d8b24e3 - React-RuntimeApple: 3df6788cd9b938bb8cb28298d80b5fbd98a4d852 - React-RuntimeCore: fad8adb4172c414c00ff6980250caf35601a0f5d - React-runtimeexecutor: d2db7e72d97751855ea0bf5273d2ac84e5ea390c - React-RuntimeHermes: 04faa4cf9a285136a6d73738787fe36020170613 - React-runtimescheduler: f6a1c9555e7131b4a8b64cce01489ad0405f6e8d - React-timing: 1e6a8acb66e2b7ac9d418956617fd1fdb19322fd - React-utils: 52bbb03f130319ef82e4c3bc7a85eaacdb1fec87 - ReactAppDependencyProvider: 433ddfb4536948630aadd5bd925aff8a632d2fe3 - ReactCodegen: 64dbbed4e9e0264d799578ea78492479a66fba4a - ReactCommon: 394c6b92765cf6d211c2c3f7f6bc601dffb316a6 - ReactNativeHost: f5e054387e917216a2a021a3f7fdc4f9f158e7e4 - ReactTestApp-DevSupport: 9b7bbba5e8fed998e763809171d9906a1375f9d3 + React-renderercss: cef3f26df2ddec558ce3c0790fc574b4fb62ce67 + React-rendererdebug: e68433ae67738caeb672a6c8cc993e9276b298a9 + React-RuntimeApple: dc1d4709bf847bc695dbe6e8aaf3e22ef25aef02 + React-RuntimeCore: ca3473c8b6578693fa3bad4d44240098d49d6723 + React-runtimeexecutor: 0db3ca0b09cd72489cef3a3729349b3c2cf13320 + React-RuntimeHermes: f92cabaf97ef2546a74360eddfc1c74a34cb9ff8 + React-runtimescheduler: 06aea75069e0d556a75d258bfc89eb0ebd5d557e + React-timing: 1a90df9a04d8e7fd165ff7fa0918b9595c776373 + React-utils: 92115441fb55ce01ded4abfb5e9336a74cd93e9c + ReactAppDependencyProvider: b20fba6c3d091a393925890009999472c8f94d95 + ReactCodegen: cf03d376a26d393f818d511240b026fc8c95313c + ReactCommon: 00df7b9f859c9d02181844255bb89a8bca544374 + ReactNativeHost: b63ce830e7c5b4e3adcf556b2ef41665da189da0 + ReactTestApp-DevSupport: c7bff1aee7663f2fb1eefcf60c41573f02916c41 ReactTestApp-Resources: 1bd9ff10e4c24f2ad87101a32023721ae923bccf - RNGestureHandler: e37bdb684df1ac17c7e1d8f71a3311b2793c186b - RNReanimated: 9d012d4031abc9df896f8a82f9928eb2b9eae417 - RNWorklets: 0da2552f9ff5d17506918a692304110cfebb9f0a + RNGestureHandler: 92ad734ef0da16d69d0a325b7e1e9ae80bdce1f9 + RNReanimated: f02fb52cfc20b2255887d44633ddf5e9bcff73b1 + RNWorklets: 99f43a35141998a990ccff4ecc685cf2ef8fbe8a SocketRocket: d4aabe649be1e368d1318fdf28a022d714d65748 - VisionCamera: 8c913d0cb2c868f779035fb69a1e0ab69e10f1c3 - VisionCameraWorklets: cc88e3e6d7304e2c00a95cae4f728aec5a6758c1 - Yoga: a3ed390a19db0459bd6839823a6ac6d9c6db198d + VisionCamera: fa37d864bf901b5a0bdef4cd155ab1c62f3147f9 + VisionCameraWorklets: a11eb167fa85d14615b9ccb7892f6509c81c3e72 + Yoga: 922d794dce2af9c437f864bf4093abfa7a131adb PODFILE CHECKSUM: 22a8651333bf096f67ca333598bd33455d994c1f -COCOAPODS: 1.16.2 +COCOAPODS: 1.15.2 diff --git a/externals/dawn b/externals/dawn index 63f25feec..1e8972751 160000 --- a/externals/dawn +++ b/externals/dawn @@ -1 +1 @@ -Subproject commit 63f25feec51e9351fb25222b6d5de1af791d7c4f +Subproject commit 1e897275172a23f27b0022fa6beae3084ed54a9b diff --git a/packages/webgpu/CONTRIBUTING.md b/packages/webgpu/CONTRIBUTING.md index b98847007..ec871cbe0 100644 --- a/packages/webgpu/CONTRIBUTING.md +++ b/packages/webgpu/CONTRIBUTING.md @@ -26,11 +26,11 @@ The Expo config plugin lives in `plugin/src` and is compiled to `plugin/build` b The Dawn version tracks the one shipped by `@shopify/react-native-skia` Graphite builds: the pin is the exact Dawn commit from the Skia milestone's DEPS file (`third_party/externals/dawn` in Skia's DEPS). It is recorded in two places that must stay in sync: - the `externals/dawn` submodule gitlink (the commit the submodule points at) -- `packages/webgpu/package.json` → `"dawn"` (a human-readable label, e.g. `chrome-m150`; Skia milestones mirror Chrome milestones) and `"dawnCommit"` (the exact commit hash) +- `packages/webgpu/package.json` → `"dawn"` (a human-readable label, e.g. `chrome-m152`; Skia milestones mirror Chrome milestones) and `"dawnCommit"` (the exact commit hash) The **Build Dawn** workflow verifies the gitlink matches `dawnCommit` and fails otherwise. -`yarn install-dawn` downloads **prebuilt** binaries from a GitHub release on this repo tagged `dawn-` (e.g. `dawn-chrome-m150`). `yarn build-dawn` builds the same binaries from the submodule source instead. +`yarn install-dawn` downloads **prebuilt** binaries from a GitHub release on this repo tagged `dawn-` (e.g. `dawn-chrome-m152`). `yarn build-dawn` builds the same binaries from the submodule source instead. Steps to bump to a new Dawn version (new Skia milestone `m`): @@ -50,4 +50,8 @@ Steps to bump to a new Dawn version (new Skia milestone `m`): cd packages/webgpu && yarn install-dawn ``` -5. **Verify and commit.** Build and run the example app, then commit the submodule bump together with the updated `package.json`. \ No newline at end of file +5. **Map the new feature names.** A milestone usually adds `wgpu::FeatureName` values. Add them to `RNWGPU_FOR_EACH_FEATURE_NAME` in `cpp/rnwgpu/api/GPUFeatures.h`, which is the single list both conversion directions are generated from; `src/__tests__/FeatureNames.spec.ts` diffs it against the installed `webgpu_cpp.h` and fails when one is missing. + +6. **Update the compatibility table** in `apps/docs/content/docs/integrations/react-native-skia.mdx` with the new milestone row, so users can pair react-native-webgpu and `@shopify/react-native-skia` versions. + +7. **Verify and commit.** Build and run the example app, then commit the submodule bump together with the updated `package.json`. \ No newline at end of file diff --git a/packages/webgpu/cpp/rnwgpu/api/GPUFeatures.h b/packages/webgpu/cpp/rnwgpu/api/GPUFeatures.h index a4faa3d98..ac19c4c6d 100644 --- a/packages/webgpu/cpp/rnwgpu/api/GPUFeatures.h +++ b/packages/webgpu/cpp/rnwgpu/api/GPUFeatures.h @@ -8,195 +8,124 @@ namespace rnwgpu { +// Single source of truth for the wgpu::FeatureName <-> GPUFeatureName string +// mapping. Every conversion (both directions, here and in EnumMapper, see +// api/descriptors/Unions.h) is derived from this list so the tables cannot +// drift apart. +// +// The list must cover every value of wgpu::FeatureName. Dawn adds features on +// every milestone upgrade; FeatureNames.spec.ts diffs this list against the +// enum in the installed webgpu_cpp.h and fails when one is missing. +#define RNWGPU_FOR_EACH_FEATURE_NAME(V) \ + V(CoreFeaturesAndLimits, "core-features-and-limits") \ + V(DepthClipControl, "depth-clip-control") \ + V(Depth32FloatStencil8, "depth32float-stencil8") \ + V(TextureCompressionBC, "texture-compression-bc") \ + V(TextureCompressionBCSliced3D, "texture-compression-bc-sliced-3d") \ + V(TextureCompressionETC2, "texture-compression-etc2") \ + V(TextureCompressionASTC, "texture-compression-astc") \ + V(TextureCompressionASTCSliced3D, "texture-compression-astc-sliced-3d") \ + V(TimestampQuery, "timestamp-query") \ + V(IndirectFirstInstance, "indirect-first-instance") \ + V(ShaderF16, "shader-f16") \ + V(RG11B10UfloatRenderable, "rg11b10ufloat-renderable") \ + V(BGRA8UnormStorage, "bgra8unorm-storage") \ + V(Float32Filterable, "float32-filterable") \ + V(Float32Blendable, "float32-blendable") \ + V(ClipDistances, "clip-distances") \ + V(DualSourceBlending, "dual-source-blending") \ + V(Subgroups, "subgroups") \ + V(TextureFormatsTier1, "texture-formats-tier1") \ + V(TextureFormatsTier2, "texture-formats-tier2") \ + V(PrimitiveIndex, "primitive-index") \ + V(TextureComponentSwizzle, "texture-component-swizzle") \ + V(SubgroupSizeControl, "subgroup-size-control") \ + V(DawnInternalUsages, "dawn-internal-usages") \ + V(DawnMultiPlanarFormats, "dawn-multi-planar-formats") \ + V(DawnNative, "dawn-native") \ + V(ChromiumExperimentalTimestampQueryInsidePasses, \ + "chromium-experimental-timestamp-query-inside-passes") \ + V(ImplicitDeviceSynchronization, "implicit-device-synchronization") \ + V(TransientAttachments, "transient-attachments") \ + V(MSAARenderToSingleSampled, "msaa-render-to-single-sampled") \ + V(D3D11MultithreadProtected, "d3d11-multithread-protected") \ + V(ANGLETextureSharing, "angle-texture-sharing") \ + V(PixelLocalStorageCoherent, "pixel-local-storage-coherent") \ + V(PixelLocalStorageNonCoherent, "pixel-local-storage-non-coherent") \ + V(Unorm16TextureFormats, "unorm16-texture-formats") \ + V(MultiPlanarFormatExtendedUsages, "multi-planar-format-extended-usages") \ + V(MultiPlanarFormatP010, "multi-planar-format-p010") \ + V(HostMappedPointer, "host-mapped-pointer") \ + V(MultiPlanarRenderTargets, "multi-planar-render-targets") \ + V(MultiPlanarFormatNv12a, "multi-planar-format-nv12a") \ + V(FramebufferFetch, "framebuffer-fetch") \ + V(BufferMapExtendedUsages, "buffer-map-extended-usages") \ + V(AdapterPropertiesMemoryHeaps, "adapter-properties-memory-heaps") \ + V(AdapterPropertiesD3D, "adapter-properties-d3d") \ + V(AdapterPropertiesVk, "adapter-properties-vk") \ + V(DawnFormatCapabilities, "format-capabilities") \ + V(DawnDrmFormatCapabilities, "drm-format-capabilities") \ + V(MultiPlanarFormatNv16, "multi-planar-format-nv16") \ + V(MultiPlanarFormatNv24, "multi-planar-format-nv24") \ + V(MultiPlanarFormatP210, "multi-planar-format-p210") \ + V(MultiPlanarFormatP410, "multi-planar-format-p410") \ + V(SharedTextureMemoryVkDedicatedAllocation, \ + "shared-texture-memory-vk-dedicated-allocation") \ + V(SharedTextureMemoryAHardwareBuffer, \ + "shared-texture-memory-ahardware-buffer") \ + V(SharedTextureMemoryDmaBuf, "shared-texture-memory-dma-buf") \ + V(SharedTextureMemoryOpaqueFD, "shared-texture-memory-opaque-fd") \ + V(SharedTextureMemoryZirconHandle, "shared-texture-memory-zircon-handle") \ + V(SharedTextureMemoryDXGISharedHandle, \ + "shared-texture-memory-dxgi-shared-handle") \ + V(SharedTextureMemoryD3D11Texture2D, \ + "shared-texture-memory-d3d11-texture2d") \ + V(SharedTextureMemoryIOSurface, "shared-texture-memory-iosurface") \ + V(SharedTextureMemoryEGLImage, "shared-texture-memory-egl-image") \ + V(SharedFenceVkSemaphoreOpaqueFD, "shared-fence-vk-semaphore-opaque-fd") \ + V(SharedFenceSyncFD, "shared-fence-sync-fd") \ + V(SharedFenceVkSemaphoreZirconHandle, \ + "shared-fence-vk-semaphore-zircon-handle") \ + V(SharedFenceDXGISharedHandle, "shared-fence-dxgi-shared-handle") \ + V(SharedFenceMTLSharedEvent, "shared-fence-mtl-shared-event") \ + V(SharedBufferMemoryD3D12Resource, "shared-buffer-memory-d3d12-resource") \ + V(StaticSamplers, "static-samplers") \ + V(YCbCrVulkanSamplers, "ycbcr-vulkan-samplers") \ + V(ShaderModuleCompilationOptions, "shader-module-compilation-options") \ + V(DawnLoadResolveTexture, "dawn-load-resolve-texture") \ + V(DawnPartialLoadResolveTexture, "dawn-partial-load-resolve-texture") \ + V(MultiDrawIndirect, "multi-draw-indirect") \ + V(DawnTexelCopyBufferRowAlignment, "dawn-texel-copy-buffer-row-alignment") \ + V(FlexibleTextureViews, "flexible-texture-views") \ + V(ChromiumExperimentalSubgroupMatrix, \ + "chromium-experimental-subgroups-matrix") \ + V(SharedFenceEGLSync, "shared-fence-egl-sync") \ + V(DawnDeviceAllocatorControl, "dawn-device-allocator-control") \ + V(AdapterPropertiesWGPU, "adapter-properties-wgpu") \ + V(SharedBufferMemoryFromWindowsHandle, \ + "shared-buffer-memory-from-windows-handle") \ + V(SharedTextureMemoryD3D12Resource, "shared-texture-memory-d3d12-resource") \ + V(ChromiumExperimentalSamplingResourceTable, \ + "chromium-experimental-sampling-resource-table") \ + V(AtomicVec2uMinMax, "atomic-vec2u-min-max") \ + V(Unorm16FormatsForExternalTexture, "unorm16-formats-for-external-texture") \ + V(OpaqueYCbCrAndroidForExternalTexture, \ + "opaque-ycbcr-android-for-external-texture") \ + V(Unorm16Filterable, "unorm16-filterable") \ + V(RenderPassRenderArea, "render-pass-render-area") \ + V(AdapterPropertiesDrm, "adapter-properties-drm") \ + V(TextureCompressionUnaligned, "texture-compression-unaligned") \ + V(DawnAllowUndefinedLoadStoreOp, "dawn-allow-undefined-load-store-op") + static void convertEnumToJSUnion(wgpu::FeatureName inEnum, std::string *outUnion) { switch (inEnum) { - case wgpu::FeatureName::DepthClipControl: - *outUnion = "depth-clip-control"; - break; - case wgpu::FeatureName::Depth32FloatStencil8: - *outUnion = "depth32float-stencil8"; - break; - case wgpu::FeatureName::TimestampQuery: - *outUnion = "timestamp-query"; - break; - case wgpu::FeatureName::TextureCompressionBC: - *outUnion = "texture-compression-bc"; - break; - case wgpu::FeatureName::TextureCompressionETC2: - *outUnion = "texture-compression-etc2"; - break; - case wgpu::FeatureName::TextureCompressionASTC: - *outUnion = "texture-compression-astc"; - break; - case wgpu::FeatureName::IndirectFirstInstance: - *outUnion = "indirect-first-instance"; - break; - case wgpu::FeatureName::ShaderF16: - *outUnion = "shader-f16"; - break; - case wgpu::FeatureName::RG11B10UfloatRenderable: - *outUnion = "rg11b10ufloat-renderable"; - break; - case wgpu::FeatureName::BGRA8UnormStorage: - *outUnion = "bgra8unorm-storage"; - break; - case wgpu::FeatureName::Float32Filterable: - *outUnion = "float32-filterable"; - break; - case wgpu::FeatureName::Subgroups: - *outUnion = "subgroups"; - break; - case wgpu::FeatureName::DawnInternalUsages: - *outUnion = "dawn-internal-usages"; - break; - case wgpu::FeatureName::DawnMultiPlanarFormats: - *outUnion = "dawn-multi-planar-formats"; - break; - case wgpu::FeatureName::DawnNative: - *outUnion = "dawn-native"; - break; - case wgpu::FeatureName::ChromiumExperimentalTimestampQueryInsidePasses: - *outUnion = "chromium-experimental-timestamp-query-inside-passes"; - break; - case wgpu::FeatureName::ImplicitDeviceSynchronization: - *outUnion = "implicit-device-synchronization"; - break; - case wgpu::FeatureName::TransientAttachments: - *outUnion = "transient-attachments"; - break; - case wgpu::FeatureName::MSAARenderToSingleSampled: - *outUnion = "msaa-render-to-single-sampled"; - break; - case wgpu::FeatureName::DualSourceBlending: - *outUnion = "dual-source-blending"; - break; - case wgpu::FeatureName::D3D11MultithreadProtected: - *outUnion = "d3d11-multithread-protected"; - break; - case wgpu::FeatureName::ANGLETextureSharing: - *outUnion = "angle-texture-sharing"; - break; - case wgpu::FeatureName::ChromiumExperimentalSubgroupMatrix: - *outUnion = "chromium-experimental-subgroups-matrix"; - break; - case wgpu::FeatureName::PixelLocalStorageCoherent: - *outUnion = "pixel-local-storage-coherent"; - break; - case wgpu::FeatureName::PixelLocalStorageNonCoherent: - *outUnion = "pixel-local-storage-non-coherent"; - break; - case wgpu::FeatureName::Unorm16TextureFormats: - *outUnion = "unorm16-texture-formats"; - break; - case wgpu::FeatureName::MultiPlanarFormatExtendedUsages: - *outUnion = "multi-planar-format-extended-usages"; - break; - case wgpu::FeatureName::MultiPlanarFormatP010: - *outUnion = "multi-planar-format-p010"; - break; - case wgpu::FeatureName::HostMappedPointer: - *outUnion = "host-mapped-pointer"; - break; - case wgpu::FeatureName::MultiPlanarRenderTargets: - *outUnion = "multi-planar-render-targets"; - break; - case wgpu::FeatureName::MultiPlanarFormatNv12a: - *outUnion = "multi-planar-format-nv12a"; - break; - case wgpu::FeatureName::FramebufferFetch: - *outUnion = "framebuffer-fetch"; - break; - case wgpu::FeatureName::BufferMapExtendedUsages: - *outUnion = "buffer-map-extended-usages"; - break; - case wgpu::FeatureName::AdapterPropertiesMemoryHeaps: - *outUnion = "adapter-properties-memory-heaps"; - break; - case wgpu::FeatureName::AdapterPropertiesD3D: - *outUnion = "adapter-properties-d3d"; - break; - case wgpu::FeatureName::AdapterPropertiesVk: - *outUnion = "adapter-properties-vk"; - break; - case wgpu::FeatureName::DawnFormatCapabilities: - *outUnion = "format-capabilities"; - break; - case wgpu::FeatureName::DawnDrmFormatCapabilities: - *outUnion = "drm-format-capabilities"; - break; - case wgpu::FeatureName::MultiPlanarFormatNv16: - *outUnion = "multi-planar-format-nv16"; - break; - case wgpu::FeatureName::MultiPlanarFormatNv24: - *outUnion = "multi-planar-format-nv24"; - break; - case wgpu::FeatureName::MultiPlanarFormatP210: - *outUnion = "multi-planar-format-p210"; - break; - case wgpu::FeatureName::MultiPlanarFormatP410: - *outUnion = "multi-planar-format-p410"; - break; - case wgpu::FeatureName::SharedTextureMemoryVkDedicatedAllocation: - *outUnion = "shared-texture-memory-vk-dedicated-allocation"; - break; - case wgpu::FeatureName::SharedTextureMemoryAHardwareBuffer: - *outUnion = "shared-texture-memory-ahardware-buffer"; - break; - case wgpu::FeatureName::SharedTextureMemoryDmaBuf: - *outUnion = "shared-texture-memory-dma-buf"; - break; - case wgpu::FeatureName::SharedTextureMemoryOpaqueFD: - *outUnion = "shared-texture-memory-opaque-fd"; - break; - case wgpu::FeatureName::SharedTextureMemoryZirconHandle: - *outUnion = "shared-texture-memory-zircon-handle"; - break; - case wgpu::FeatureName::SharedTextureMemoryDXGISharedHandle: - *outUnion = "shared-texture-memory-dxgi-shared-handle"; - break; - case wgpu::FeatureName::SharedTextureMemoryD3D11Texture2D: - *outUnion = "shared-texture-memory-d3d11-texture2d"; - break; - case wgpu::FeatureName::SharedTextureMemoryIOSurface: - *outUnion = "shared-texture-memory-iosurface"; - break; - case wgpu::FeatureName::SharedTextureMemoryEGLImage: - *outUnion = "shared-texture-memory-egl-image"; - break; - case wgpu::FeatureName::SharedFenceVkSemaphoreOpaqueFD: - *outUnion = "shared-fence-vk-semaphore-opaque-fd"; - break; - case wgpu::FeatureName::SharedFenceSyncFD: - *outUnion = "shared-fence-sync-fd"; - break; - case wgpu::FeatureName::SharedFenceVkSemaphoreZirconHandle: - *outUnion = "shared-fence-vk-semaphore-zircon-handle"; - break; - case wgpu::FeatureName::SharedFenceDXGISharedHandle: - *outUnion = "shared-fence-dxgi-shared-handle"; - break; - case wgpu::FeatureName::SharedFenceMTLSharedEvent: - *outUnion = "shared-fence-mtl-shared-event"; - break; - case wgpu::FeatureName::SharedBufferMemoryD3D12Resource: - *outUnion = "shared-buffer-memory-d3d12-resource"; - break; - case wgpu::FeatureName::StaticSamplers: - *outUnion = "static-samplers"; - break; - case wgpu::FeatureName::YCbCrVulkanSamplers: - *outUnion = "ycbcr-vulkan-samplers"; - break; - case wgpu::FeatureName::OpaqueYCbCrAndroidForExternalTexture: - *outUnion = "opaque-ycbcr-android-for-external-texture"; - break; - case wgpu::FeatureName::ShaderModuleCompilationOptions: - *outUnion = "shader-module-compilation-options"; - break; - case wgpu::FeatureName::DawnLoadResolveTexture: - *outUnion = "dawn-load-resolve-texture"; +#define RNWGPU_FEATURE_NAME_CASE(Enum, Name) \ + case wgpu::FeatureName::Enum: \ + *outUnion = Name; \ break; + RNWGPU_FOR_EACH_FEATURE_NAME(RNWGPU_FEATURE_NAME_CASE) +#undef RNWGPU_FEATURE_NAME_CASE default: fprintf(stderr, "Unknown feature name %d\n", static_cast(inEnum)); *outUnion = ""; diff --git a/packages/webgpu/cpp/rnwgpu/api/descriptors/Unions.h b/packages/webgpu/cpp/rnwgpu/api/descriptors/Unions.h index bf3958295..88303c75d 100644 --- a/packages/webgpu/cpp/rnwgpu/api/descriptors/Unions.h +++ b/packages/webgpu/cpp/rnwgpu/api/descriptors/Unions.h @@ -4,6 +4,7 @@ #include "EnumMapper.h" #include "External.h" +#include "GPUFeatures.h" #include "webgpu/webgpu_cpp.h" namespace rnwgpu { @@ -410,328 +411,25 @@ inline void convertEnumToJSUnion(wgpu::ErrorFilter inEnum, inline void convertJSUnionToEnum(const std::string &inUnion, wgpu::FeatureName *outEnum) { - if (inUnion == "depth-clip-control") { - *outEnum = wgpu::FeatureName::DepthClipControl; - } else if (inUnion == "depth32float-stencil8") { - *outEnum = wgpu::FeatureName::Depth32FloatStencil8; - } else if (inUnion == "texture-compression-bc") { - *outEnum = wgpu::FeatureName::TextureCompressionBC; - } else if (inUnion == "texture-compression-etc2") { - *outEnum = wgpu::FeatureName::TextureCompressionETC2; - } else if (inUnion == "texture-compression-astc") { - *outEnum = wgpu::FeatureName::TextureCompressionASTC; - } else if (inUnion == "timestamp-query") { - *outEnum = wgpu::FeatureName::TimestampQuery; - } else if (inUnion == "indirect-first-instance") { - *outEnum = wgpu::FeatureName::IndirectFirstInstance; - } else if (inUnion == "shader-f16") { - *outEnum = wgpu::FeatureName::ShaderF16; - } else if (inUnion == "rg11b10ufloat-renderable") { - *outEnum = wgpu::FeatureName::RG11B10UfloatRenderable; - } else if (inUnion == "bgra8unorm-storage") { - *outEnum = wgpu::FeatureName::BGRA8UnormStorage; - } else if (inUnion == "float32-filterable") { - *outEnum = wgpu::FeatureName::Float32Filterable; - } else if (inUnion == "subgroups") { - *outEnum = wgpu::FeatureName::Subgroups; - } else if (inUnion == "dawn-internal-usages") { - *outEnum = wgpu::FeatureName::DawnInternalUsages; - } else if (inUnion == "dawn-multi-planar-formats") { - *outEnum = wgpu::FeatureName::DawnMultiPlanarFormats; - } else if (inUnion == "dawn-native") { - *outEnum = wgpu::FeatureName::DawnNative; - } else if (inUnion == "chromium-experimental-timestamp-query-inside-passes") { - *outEnum = - wgpu::FeatureName::ChromiumExperimentalTimestampQueryInsidePasses; - } else if (inUnion == "implicit-device-synchronization") { - *outEnum = wgpu::FeatureName::ImplicitDeviceSynchronization; - } else if (inUnion == "transient-attachments") { - *outEnum = wgpu::FeatureName::TransientAttachments; - } else if (inUnion == "msaa-render-to-single-sampled") { - *outEnum = wgpu::FeatureName::MSAARenderToSingleSampled; - } else if (inUnion == "dual-source-blending") { - *outEnum = wgpu::FeatureName::DualSourceBlending; - } else if (inUnion == "d3d11-multithread-protected") { - *outEnum = wgpu::FeatureName::D3D11MultithreadProtected; - } else if (inUnion == "angle-texture-sharing") { - *outEnum = wgpu::FeatureName::ANGLETextureSharing; - } else if (inUnion == "chromium-experimental-subgroups-matrix") { - *outEnum = wgpu::FeatureName::ChromiumExperimentalSubgroupMatrix; - } else if (inUnion == "pixel-local-storage-coherent") { - *outEnum = wgpu::FeatureName::PixelLocalStorageCoherent; - } else if (inUnion == "pixel-local-storage-non-coherent") { - *outEnum = wgpu::FeatureName::PixelLocalStorageNonCoherent; - } else if (inUnion == "unorm16-texture-formats") { - *outEnum = wgpu::FeatureName::Unorm16TextureFormats; - } else if (inUnion == "multi-planar-format-extended-usages") { - *outEnum = wgpu::FeatureName::MultiPlanarFormatExtendedUsages; - } else if (inUnion == "multi-planar-format-p010") { - *outEnum = wgpu::FeatureName::MultiPlanarFormatP010; - } else if (inUnion == "host-mapped-pointer") { - *outEnum = wgpu::FeatureName::HostMappedPointer; - } else if (inUnion == "multi-planar-render-targets") { - *outEnum = wgpu::FeatureName::MultiPlanarRenderTargets; - } else if (inUnion == "multi-planar-format-nv12a") { - *outEnum = wgpu::FeatureName::MultiPlanarFormatNv12a; - } else if (inUnion == "framebuffer-fetch") { - *outEnum = wgpu::FeatureName::FramebufferFetch; - } else if (inUnion == "buffer-map-extended-usages") { - *outEnum = wgpu::FeatureName::BufferMapExtendedUsages; - } else if (inUnion == "adapter-properties-memory-heaps") { - *outEnum = wgpu::FeatureName::AdapterPropertiesMemoryHeaps; - } else if (inUnion == "adapter-properties-d3d") { - *outEnum = wgpu::FeatureName::AdapterPropertiesD3D; - } else if (inUnion == "adapter-properties-vk") { - *outEnum = wgpu::FeatureName::AdapterPropertiesVk; - } else if (inUnion == "format-capabilities") { - *outEnum = wgpu::FeatureName::DawnFormatCapabilities; - } else if (inUnion == "multi-planar-format-nv16") { - *outEnum = wgpu::FeatureName::MultiPlanarFormatNv16; - } else if (inUnion == "multi-planar-format-nv24") { - *outEnum = wgpu::FeatureName::MultiPlanarFormatNv24; - } else if (inUnion == "multi-planar-format-p210") { - *outEnum = wgpu::FeatureName::MultiPlanarFormatP210; - } else if (inUnion == "multi-planar-format-p410") { - *outEnum = wgpu::FeatureName::MultiPlanarFormatP410; - } else if (inUnion == "shared-texture-memory-vk-dedicated-allocation") { - *outEnum = wgpu::FeatureName::SharedTextureMemoryVkDedicatedAllocation; - } else if (inUnion == "shared-texture-memory-ahardware-buffer") { - *outEnum = wgpu::FeatureName::SharedTextureMemoryAHardwareBuffer; - } else if (inUnion == "shared-texture-memory-dma-buf") { - *outEnum = wgpu::FeatureName::SharedTextureMemoryDmaBuf; - } else if (inUnion == "shared-texture-memory-opaque-fd") { - *outEnum = wgpu::FeatureName::SharedTextureMemoryOpaqueFD; - } else if (inUnion == "shared-texture-memory-zircon-handle") { - *outEnum = wgpu::FeatureName::SharedTextureMemoryZirconHandle; - } else if (inUnion == "shared-texture-memory-dxgi-shared-handle") { - *outEnum = wgpu::FeatureName::SharedTextureMemoryDXGISharedHandle; - } else if (inUnion == "shared-texture-memory-d3d11-texture2d") { - *outEnum = wgpu::FeatureName::SharedTextureMemoryD3D11Texture2D; - } else if (inUnion == "shared-texture-memory-iosurface") { - *outEnum = wgpu::FeatureName::SharedTextureMemoryIOSurface; - } else if (inUnion == "shared-texture-memory-egl-image") { - *outEnum = wgpu::FeatureName::SharedTextureMemoryEGLImage; - } else if (inUnion == "shared-fence-vk-semaphore-opaque-fd") { - *outEnum = wgpu::FeatureName::SharedFenceVkSemaphoreOpaqueFD; - } else if (inUnion == "shared-fence-sync-fd") { - *outEnum = wgpu::FeatureName::SharedFenceSyncFD; - } else if (inUnion == "shared-fence-vk-semaphore-zircon-handle") { - *outEnum = wgpu::FeatureName::SharedFenceVkSemaphoreZirconHandle; - } else if (inUnion == "shared-fence-dxgi-shared-handle") { - *outEnum = wgpu::FeatureName::SharedFenceDXGISharedHandle; - } else if (inUnion == "shared-fence-mtl-shared-event") { - *outEnum = wgpu::FeatureName::SharedFenceMTLSharedEvent; - } else if (inUnion == "shared-buffer-memory-d3d12-resource") { - *outEnum = wgpu::FeatureName::SharedBufferMemoryD3D12Resource; - } else if (inUnion == "static-samplers") { - *outEnum = wgpu::FeatureName::StaticSamplers; - } else if (inUnion == "ycbcr-vulkan-samplers") { - *outEnum = wgpu::FeatureName::YCbCrVulkanSamplers; - } else if (inUnion == "opaque-ycbcr-android-for-external-texture") { - *outEnum = wgpu::FeatureName::OpaqueYCbCrAndroidForExternalTexture; - } else if (inUnion == "shader-module-compilation-options") { - *outEnum = wgpu::FeatureName::ShaderModuleCompilationOptions; - } else if (inUnion == "dawn-load-resolve-texture") { - *outEnum = wgpu::FeatureName::DawnLoadResolveTexture; - } else if (inUnion == "clip-distances") { - *outEnum = wgpu::FeatureName::ClipDistances; - } else { - throw invalidUnion(inUnion); +#define RNWGPU_FEATURE_NAME_IF(Enum, Name) \ + if (inUnion == Name) { \ + *outEnum = wgpu::FeatureName::Enum; \ + return; \ } + RNWGPU_FOR_EACH_FEATURE_NAME(RNWGPU_FEATURE_NAME_IF) +#undef RNWGPU_FEATURE_NAME_IF + throw invalidUnion(inUnion); } inline void convertEnumToJSUnion(wgpu::FeatureName inEnum, std::string *outUnion) { switch (inEnum) { - case wgpu::FeatureName::DepthClipControl: - *outUnion = "depth-clip-control"; - break; - case wgpu::FeatureName::Depth32FloatStencil8: - *outUnion = "depth32float-stencil8"; - break; - case wgpu::FeatureName::TextureCompressionBC: - *outUnion = "texture-compression-bc"; - break; - case wgpu::FeatureName::TextureCompressionETC2: - *outUnion = "texture-compression-etc2"; - break; - case wgpu::FeatureName::TextureCompressionASTC: - *outUnion = "texture-compression-astc"; - break; - case wgpu::FeatureName::TimestampQuery: - *outUnion = "timestamp-query"; - break; - case wgpu::FeatureName::IndirectFirstInstance: - *outUnion = "indirect-first-instance"; - break; - case wgpu::FeatureName::ShaderF16: - *outUnion = "shader-f16"; - break; - case wgpu::FeatureName::RG11B10UfloatRenderable: - *outUnion = "rg11b10ufloat-renderable"; - break; - case wgpu::FeatureName::BGRA8UnormStorage: - *outUnion = "bgra8unorm-storage"; - break; - case wgpu::FeatureName::Float32Filterable: - *outUnion = "float32-filterable"; - break; - case wgpu::FeatureName::Subgroups: - *outUnion = "subgroups"; - break; - case wgpu::FeatureName::DawnInternalUsages: - *outUnion = "dawn-internal-usages"; - break; - case wgpu::FeatureName::DawnMultiPlanarFormats: - *outUnion = "dawn-multi-planar-formats"; - break; - case wgpu::FeatureName::DawnNative: - *outUnion = "dawn-native"; - break; - case wgpu::FeatureName::DawnFormatCapabilities: - *outUnion = "format-capabilities"; - break; - case wgpu::FeatureName::ChromiumExperimentalTimestampQueryInsidePasses: - *outUnion = "chromium-experimental-timestamp-query-inside-passes"; - break; - case wgpu::FeatureName::ImplicitDeviceSynchronization: - *outUnion = "implicit-device-synchronization"; - break; - // case wgpu::FeatureName::SurfaceCapabilities: - // *outUnion = "surface-capabilities"; - // break; - case wgpu::FeatureName::TransientAttachments: - *outUnion = "transient-attachments"; - break; - case wgpu::FeatureName::MSAARenderToSingleSampled: - *outUnion = "msaa-render-to-single-sampled"; - break; - case wgpu::FeatureName::DualSourceBlending: - *outUnion = "dual-source-blending"; - break; - case wgpu::FeatureName::D3D11MultithreadProtected: - *outUnion = "d3d11-multithread-protected"; - break; - case wgpu::FeatureName::ANGLETextureSharing: - *outUnion = "angle-texture-sharing"; - break; - case wgpu::FeatureName::ChromiumExperimentalSubgroupMatrix: - *outUnion = "chromium-experimental-subgroups-matrix"; - break; - case wgpu::FeatureName::PixelLocalStorageCoherent: - *outUnion = "pixel-local-storage-coherent"; - break; - case wgpu::FeatureName::PixelLocalStorageNonCoherent: - *outUnion = "pixel-local-storage-non-coherent"; - break; - case wgpu::FeatureName::Unorm16TextureFormats: - *outUnion = "unorm16-texture-formats"; - break; - case wgpu::FeatureName::MultiPlanarFormatExtendedUsages: - *outUnion = "multi-planar-format-extended-usages"; - break; - case wgpu::FeatureName::MultiPlanarFormatP010: - *outUnion = "multi-planar-format-p010"; - break; - case wgpu::FeatureName::HostMappedPointer: - *outUnion = "host-mapped-pointer"; - break; - case wgpu::FeatureName::MultiPlanarRenderTargets: - *outUnion = "multi-planar-render-targets"; - break; - case wgpu::FeatureName::MultiPlanarFormatNv12a: - *outUnion = "multi-planar-format-nv12a"; - break; - case wgpu::FeatureName::FramebufferFetch: - *outUnion = "framebuffer-fetch"; - break; - case wgpu::FeatureName::BufferMapExtendedUsages: - *outUnion = "buffer-map-extended-usages"; - break; - case wgpu::FeatureName::AdapterPropertiesMemoryHeaps: - *outUnion = "adapter-properties-memory-heaps"; - break; - case wgpu::FeatureName::AdapterPropertiesD3D: - *outUnion = "adapter-properties-d3d"; - break; - case wgpu::FeatureName::AdapterPropertiesVk: - *outUnion = "adapter-properties-vk"; - break; - case wgpu::FeatureName::MultiPlanarFormatNv16: - *outUnion = "multi-planar-format-nv16"; - break; - case wgpu::FeatureName::MultiPlanarFormatNv24: - *outUnion = "multi-planar-format-nv24"; - break; - case wgpu::FeatureName::MultiPlanarFormatP210: - *outUnion = "multi-planar-format-p210"; - break; - case wgpu::FeatureName::MultiPlanarFormatP410: - *outUnion = "multi-planar-format-p410"; - break; - case wgpu::FeatureName::SharedTextureMemoryVkDedicatedAllocation: - *outUnion = "shared-texture-memory-vk-dedicated-allocation"; - break; - case wgpu::FeatureName::SharedTextureMemoryAHardwareBuffer: - *outUnion = "shared-texture-memory-ahardware-buffer"; - break; - case wgpu::FeatureName::SharedTextureMemoryDmaBuf: - *outUnion = "shared-texture-memory-dma-buf"; - break; - case wgpu::FeatureName::SharedTextureMemoryOpaqueFD: - *outUnion = "shared-texture-memory-opaque-fd"; - break; - case wgpu::FeatureName::SharedTextureMemoryZirconHandle: - *outUnion = "shared-texture-memory-zircon-handle"; - break; - case wgpu::FeatureName::SharedTextureMemoryDXGISharedHandle: - *outUnion = "shared-texture-memory-dxgi-shared-handle"; - break; - case wgpu::FeatureName::SharedTextureMemoryD3D11Texture2D: - *outUnion = "shared-texture-memory-d3d11-texture2d"; - break; - case wgpu::FeatureName::SharedTextureMemoryIOSurface: - *outUnion = "shared-texture-memory-iosurface"; - break; - case wgpu::FeatureName::SharedTextureMemoryEGLImage: - *outUnion = "shared-texture-memory-egl-image"; - break; - case wgpu::FeatureName::SharedFenceVkSemaphoreOpaqueFD: - *outUnion = "shared-fence-vk-semaphore-opaque-fd"; - break; - case wgpu::FeatureName::SharedFenceSyncFD: - *outUnion = "shared-fence-sync-fd"; - break; - case wgpu::FeatureName::SharedFenceVkSemaphoreZirconHandle: - *outUnion = "shared-fence-vk-semaphore-zircon-handle"; - break; - case wgpu::FeatureName::SharedFenceDXGISharedHandle: - *outUnion = "shared-fence-dxgi-shared-handle"; - break; - case wgpu::FeatureName::SharedFenceMTLSharedEvent: - *outUnion = "shared-fence-mtl-shared-event"; - break; - case wgpu::FeatureName::SharedBufferMemoryD3D12Resource: - *outUnion = "shared-buffer-memory-d3d12-resource"; - break; - case wgpu::FeatureName::StaticSamplers: - *outUnion = "static-samplers"; - break; - case wgpu::FeatureName::YCbCrVulkanSamplers: - *outUnion = "ycbcr-vulkan-samplers"; - break; - case wgpu::FeatureName::OpaqueYCbCrAndroidForExternalTexture: - *outUnion = "opaque-ycbcr-android-for-external-texture"; - break; - case wgpu::FeatureName::ShaderModuleCompilationOptions: - *outUnion = "shader-module-compilation-options"; - break; - case wgpu::FeatureName::DawnLoadResolveTexture: - *outUnion = "dawn-load-resolve-texture"; - break; - case wgpu::FeatureName::ClipDistances: - *outUnion = "clip-distances"; +#define RNWGPU_FEATURE_NAME_CASE(Enum, Name) \ + case wgpu::FeatureName::Enum: \ + *outUnion = Name; \ break; + RNWGPU_FOR_EACH_FEATURE_NAME(RNWGPU_FEATURE_NAME_CASE) +#undef RNWGPU_FEATURE_NAME_CASE default: throw invalidEnum(inEnum); } diff --git a/packages/webgpu/package.json b/packages/webgpu/package.json index 0f3475580..65ab7d84e 100644 --- a/packages/webgpu/package.json +++ b/packages/webgpu/package.json @@ -23,8 +23,8 @@ "app.plugin.js", "plugin/build/**" ], - "dawn": "chrome-m150", - "dawnCommit": "63f25feec51e9351fb25222b6d5de1af791d7c4f", + "dawn": "chrome-m152", + "dawnCommit": "1e897275172a23f27b0022fa6beae3084ed54a9b", "scripts": { "test": "NODE_OPTIONS='--experimental-require-module' jest -i", "test:ref": "REFERENCE=true NODE_OPTIONS='--experimental-require-module' jest -i", diff --git a/packages/webgpu/scripts/install-dawn.ts b/packages/webgpu/scripts/install-dawn.ts index 345f6a3b6..9540f1d8f 100644 --- a/packages/webgpu/scripts/install-dawn.ts +++ b/packages/webgpu/scripts/install-dawn.ts @@ -75,7 +75,7 @@ if (!dawnVersion) { } // Parse the dawn version to construct the release tag -// Format: "chrome-m150" -> "dawn-chrome-m150" +// Format: "chrome-m152" -> "dawn-chrome-m152" const releaseTag = `dawn-${dawnVersion.replace("/", "-")}`; const releaseUrl = `https://github.com/wcandillon/react-native-webgpu/releases/tag/${releaseTag}`; diff --git a/packages/webgpu/src/__tests__/FeatureNames.spec.ts b/packages/webgpu/src/__tests__/FeatureNames.spec.ts new file mode 100644 index 000000000..6bfca5206 --- /dev/null +++ b/packages/webgpu/src/__tests__/FeatureNames.spec.ts @@ -0,0 +1,123 @@ +import fs from "fs"; +import path from "path"; + +import { client } from "./setup"; + +const cppDir = path.resolve(__dirname, "..", "..", "cpp"); +const read = (...segments: string[]) => + fs.readFileSync(path.join(cppDir, ...segments), "utf-8"); + +// Every value of wgpu::FeatureName, straight from the Dawn headers installed by +// `yarn install-dawn`. A milestone upgrade grows this list. +const dawnFeatureNames = () => { + const header = read("webgpu", "webgpu_cpp.h"); + const body = /enum class FeatureName[^{]*\{([\s\S]*?)\n\};/.exec(header); + if (!body) { + throw new Error("Could not find enum class FeatureName in webgpu_cpp.h"); + } + return Array.from(body[1].matchAll(/^\s*(\w+)\s*=/gm)) + .map((match) => match[1]) + .filter((name) => name !== "Undefined"); +}; + +// The single source of truth every conversion is generated from. +const mappingList = () => { + const header = read("rnwgpu", "api", "GPUFeatures.h"); + const body = /#define RNWGPU_FOR_EACH_FEATURE_NAME\(V\)([\s\S]*?)\n\n/.exec( + header, + ); + if (!body) { + throw new Error("Could not find RNWGPU_FOR_EACH_FEATURE_NAME"); + } + // `[\s\\]*` so an entry clang-format wrapped across a line continuation is + // still picked up. + return Array.from(body[1].matchAll(/V\((\w+),[\s\\]*"([^"]+)"\)/g)).map( + (match) => ({ enumerator: match[1], name: match[2] }), + ); +}; + +describe("GPUFeatureName mapping", () => { + it("maps every wgpu::FeatureName", () => { + const mapped = new Set(mappingList().map(({ enumerator }) => enumerator)); + const missing = dawnFeatureNames().filter((name) => !mapped.has(name)); + // A Dawn upgrade added features we do not convert yet: adapter.features + // would report them as "" and requiredFeatures would reject them. Add them + // to RNWGPU_FOR_EACH_FEATURE_NAME in cpp/rnwgpu/api/GPUFeatures.h. + expect(missing).toEqual([]); + }); + + it("maps no feature that Dawn does not define", () => { + const known = new Set(dawnFeatureNames()); + const stale = mappingList() + .map(({ enumerator }) => enumerator) + .filter((enumerator) => !known.has(enumerator)); + expect(stale).toEqual([]); + }); + + it("gives every feature a unique kebab-case name", () => { + const list = mappingList(); + expect(list.length).toBeGreaterThan(0); + const duplicates = list + .map(({ name }) => name) + .filter((name, index, names) => names.indexOf(name) !== index); + expect(duplicates).toEqual([]); + const malformed = list + .map(({ name }) => name) + .filter((name) => !/^[a-z0-9]+(-[a-z0-9]+)*$/.test(name)); + expect(malformed).toEqual([]); + }); + + it("derives both EnumMapper conversions from the shared list", () => { + // Guards against someone re-introducing a hand-written table that drifts + // from GPUFeatures.h, which is how these mappings fell behind before. + const unions = read("rnwgpu", "api", "descriptors", "Unions.h"); + const featureBlocks = unions + .split(/\ninline void convert/) + .filter((block) => /wgpu::FeatureName [*]?(out|in)Enum/.test(block)); + expect(featureBlocks).toHaveLength(2); + featureBlocks.forEach((block) => { + expect(block).toContain("RNWGPU_FOR_EACH_FEATURE_NAME"); + }); + }); + + it("never reports an unmapped feature on the adapter", async () => { + const features = await client.eval(({ gpu }) => + gpu.requestAdapter().then((adapter) => Array.from(adapter!.features)), + ); + expect(features.length).toBeGreaterThan(0); + // "" is what convertEnumToJSUnion falls back to for a feature it does not + // know about. + expect(features.filter((feature) => feature === "")).toEqual([]); + }); + + it("never reports an unmapped feature on the device", async () => { + const features = await client.eval(({ device }) => + Array.from(device.features), + ); + expect(features.filter((feature) => feature === "")).toEqual([]); + }); + + it("accepts every advertised feature in requiredFeatures", async () => { + // Round-trips the whole table through native: JS name -> wgpu::FeatureName + // on the way in, and back to a JS name when the device reports what it + // enabled. Requesting any subset of adapter.features must succeed. + const result = await client.eval(({ gpu }) => + gpu.requestAdapter().then((adapter) => { + const requested = Array.from(adapter!.features); + return adapter! + .requestDevice({ + requiredFeatures: requested as GPUFeatureName[], + }) + .then((device) => ({ + requested, + enabled: Array.from(device.features), + })); + }), + ); + expect(result.requested.length).toBeGreaterThan(0); + const missing = result.requested.filter( + (feature) => !result.enabled.includes(feature), + ); + expect(missing).toEqual([]); + }); +});