├── .github ├── actions │ └── setup │ │ └── action.yml └── workflows │ ├── build-dawn.yml │ ├── ci.yml │ └── cpplint.yml ├── .gitignore ├── .gitmodules ├── .nvmrc ├── .yarn ├── patches │ └── @react-three-fiber-npm-8.17.6-bc537e834c.patch └── releases │ └── yarn-3.6.4.cjs ├── .yarnrc.yml ├── LICENSE.md ├── README.md ├── apps └── example │ ├── .eslintrc │ ├── .gitignore │ ├── .watchmanconfig │ ├── android │ ├── build.gradle │ ├── gradle.properties │ ├── gradle │ │ └── wrapper │ │ │ ├── gradle-wrapper.jar │ │ │ └── gradle-wrapper.properties │ ├── gradlew │ ├── gradlew.bat │ └── settings.gradle │ ├── app.json │ ├── babel.config.js │ ├── index.js │ ├── ios │ ├── Podfile │ └── Podfile.lock │ ├── jest.config.js │ ├── macos │ ├── Podfile │ └── Podfile.lock │ ├── metro.config.js │ ├── package.json │ ├── react-native.config.js │ ├── src │ ├── ABuffer │ │ ├── ABuffer.tsx │ │ ├── Shaders.ts │ │ └── index.ts │ ├── App.tsx │ ├── CanvasAPI │ │ ├── CanvasAPI.tsx │ │ └── index.ts │ ├── ComputeBoids │ │ ├── ComputeBoids.tsx │ │ ├── Shaders.ts │ │ └── index.ts │ ├── Cube │ │ ├── Cube.tsx │ │ ├── Cubemap.tsx │ │ ├── FractalCube.tsx │ │ ├── InstancedCube.tsx │ │ ├── Shaders.ts │ │ ├── TexturedCube.tsx │ │ └── index.ts │ ├── GradientTiles │ │ ├── GradientTiles.tsx │ │ ├── gradientWgsl.ts │ │ └── index.ts │ ├── Home.tsx │ ├── MNISTInference │ │ ├── Lib.ts │ │ ├── MNISTInference.tsx │ │ └── index.ts │ ├── OcclusionQuery │ │ ├── OcclusionQuery.tsx │ │ └── index.ts │ ├── Particles │ │ ├── Particles.tsx │ │ ├── Shaders.ts │ │ └── index.ts │ ├── RenderBundles │ │ ├── RenderBundles.tsx │ │ └── index.ts │ ├── Resize │ │ ├── Resize.tsx │ │ └── index.ts │ ├── ReversedZ │ │ ├── ReversedZ.tsx │ │ ├── Shaders.ts │ │ └── index.ts │ ├── Route.ts │ ├── Sampler │ │ ├── SamplerParameters.tsx │ │ ├── Shaders.ts │ │ └── index.ts │ ├── ShadowMapping │ │ ├── DeferedRendering.tsx │ │ ├── Shaders.ts │ │ ├── ShadowMapping.tsx │ │ └── index.ts │ ├── Tensorflow │ │ ├── Platform.ts │ │ ├── Tensorflow.tsx │ │ └── index.ts │ ├── Tests.tsx │ ├── ThreeJS │ │ ├── Backdrop.tsx │ │ ├── Cube.tsx │ │ ├── Fiber.tsx │ │ ├── Helmet.tsx │ │ ├── InstancedMesh.tsx │ │ ├── List.tsx │ │ ├── PostProcessing.tsx │ │ ├── Routes.ts │ │ ├── assets │ │ │ ├── AssetManager.ts │ │ │ ├── PrimaryIonDrive.glb │ │ │ ├── helmet │ │ │ │ ├── DamagedHelmet.bin │ │ │ │ ├── DamagedHelmet.gltf │ │ │ │ ├── Default_AO.jpg │ │ │ │ ├── Default_albedo.jpg │ │ │ │ ├── Default_emissive.jpg │ │ │ │ ├── Default_metalRoughness.jpg │ │ │ │ ├── Default_normal.jpg │ │ │ │ └── royal_esplanade_1k.hdr │ │ │ ├── michelle │ │ │ │ ├── Ch03_1001_Diffuse.png │ │ │ │ ├── Ch03_1001_Glossiness.png │ │ │ │ ├── Ch03_1001_Normal.png │ │ │ │ ├── model.bin │ │ │ │ └── model.gltf │ │ │ ├── scene.bin │ │ │ ├── scene.gltf │ │ │ └── textures │ │ │ │ └── uv_grid_opengl.jpg │ │ ├── components │ │ │ ├── FiberCanvas.tsx │ │ │ ├── Matrix4.ts │ │ │ ├── OrbitControl.tsx │ │ │ └── makeWebGPURenderer.ts │ │ └── index.tsx │ ├── Triangle │ │ ├── HelloTriangle.tsx │ │ ├── HelloTriangleMSAA.tsx │ │ ├── index.ts │ │ └── triangle.ts │ ├── Wireframe │ │ ├── Shaders.ts │ │ ├── Wireframe.tsx │ │ ├── index.ts │ │ ├── models.ts │ │ └── utils.ts │ ├── assets │ │ ├── Di-3d.png │ │ ├── cubemap │ │ │ ├── credit.txt │ │ │ ├── negx.jpg │ │ │ ├── negy.jpg │ │ │ ├── negz.jpg │ │ │ ├── posx.jpg │ │ │ ├── posy.jpg │ │ │ ├── posz.jpg │ │ │ └── readme.txt │ │ ├── f.png │ │ ├── moon.png │ │ ├── react.png │ │ └── saturn.png │ ├── components │ │ ├── GUI.ts │ │ ├── Texture.tsx │ │ ├── cube.ts │ │ ├── meshes │ │ │ ├── mesh.ts │ │ │ ├── sphere.ts │ │ │ ├── stanfordDragon.ts │ │ │ ├── stanfordDragonData.ts │ │ │ ├── teapot.ts │ │ │ └── utils.ts │ │ ├── useAssets.ts │ │ ├── useWebGPU.ts │ │ └── utils.ts │ └── useClient.ts │ ├── tsconfig.json │ └── visionos │ └── Podfile ├── package.json ├── packages └── webgpu │ ├── .editorconfig │ ├── .eslintrc │ ├── .gitattributes │ ├── .gitignore │ ├── .watchmanconfig │ ├── CODE_OF_CONDUCT.md │ ├── CONTRIBUTING.md │ ├── LICENSE │ ├── README.md │ ├── android │ ├── CMakeLists.txt │ ├── build.gradle │ ├── cpp │ │ ├── AndroidPlatformContext.h │ │ ├── cpp-adapter.cpp │ │ └── platform │ │ │ └── ThreadUtils.cpp │ ├── gradle.properties │ └── src │ │ ├── main │ │ ├── AndroidManifest.xml │ │ └── java │ │ │ └── com │ │ │ └── webgpu │ │ │ ├── WebGPUAHBView.java │ │ │ ├── WebGPUAPI.java │ │ │ ├── WebGPUBaseView.java │ │ │ ├── WebGPUModule.java │ │ │ ├── WebGPUSurfaceView.java │ │ │ ├── WebGPUSurfaceViewWithSC.java │ │ │ ├── WebGPUTextureView.java │ │ │ ├── WebGPUView.java │ │ │ ├── WebGPUViewManager.java │ │ │ └── WebGPUViewPackage.java │ │ ├── newarch │ │ └── com │ │ │ └── webgpu │ │ │ └── WebGPUViewManagerSpec.java │ │ └── oldarch │ │ └── com │ │ └── webgpu │ │ ├── NativeWebGPUModuleSpec.java │ │ └── WebGPUViewManagerSpec.java │ ├── apple │ ├── ApplePlatformContext.h │ ├── ApplePlatformContext.mm │ ├── MetalView.h │ ├── MetalView.mm │ ├── RNWGUIKit.h │ ├── WebGPUModule.h │ ├── WebGPUModule.mm │ ├── WebGPUView.h │ ├── WebGPUView.mm │ ├── WebGPUViewManager.mm │ └── platform │ │ └── ThreadUtils.cpp │ ├── babel.config.js │ ├── cpp │ ├── WGPULogger.h │ ├── dawn_logging.cpp │ ├── jsi │ │ ├── RNFEnumMapper.h │ │ ├── RNFHybridObject.cpp │ │ ├── RNFHybridObject.h │ │ ├── RNFJSIConverter.h │ │ ├── RNFJSIHelper.h │ │ ├── RNFPointerHolder.h │ │ ├── RNFPromise.cpp │ │ ├── RNFPromise.h │ │ ├── RNFRuntimeCache.cpp │ │ ├── RNFRuntimeCache.h │ │ ├── RNFWorkletRuntimeCollector.h │ │ ├── RNFWorkletRuntimeRegistry.cpp │ │ └── RNFWorkletRuntimeRegistry.h │ ├── platform │ │ └── ThreadUtils.h │ ├── rnwgpu │ │ ├── ArrayBuffer.h │ │ ├── PlatformContext.h │ │ ├── RNWebGPUManager.cpp │ │ ├── RNWebGPUManager.h │ │ ├── SurfaceRegistry.h │ │ └── api │ │ │ ├── AsyncRunner.h │ │ │ ├── Canvas.h │ │ │ ├── Convertors.h │ │ │ ├── External.h │ │ │ ├── GPU.cpp │ │ │ ├── GPU.h │ │ │ ├── GPUAdapter.cpp │ │ │ ├── GPUAdapter.h │ │ │ ├── GPUAdapterInfo.h │ │ │ ├── GPUBindGroup.cpp │ │ │ ├── GPUBindGroup.h │ │ │ ├── GPUBindGroupLayout.h │ │ │ ├── GPUBuffer.cpp │ │ │ ├── GPUBuffer.h │ │ │ ├── GPUCanvasContext.cpp │ │ │ ├── GPUCanvasContext.h │ │ │ ├── GPUCommandBuffer.h │ │ │ ├── GPUCommandEncoder.cpp │ │ │ ├── GPUCommandEncoder.h │ │ │ ├── GPUCompilationInfo.h │ │ │ ├── GPUCompilationMessage.h │ │ │ ├── GPUComputePassEncoder.cpp │ │ │ ├── GPUComputePassEncoder.h │ │ │ ├── GPUComputePipeline.cpp │ │ │ ├── GPUComputePipeline.h │ │ │ ├── GPUDevice.cpp │ │ │ ├── GPUDevice.h │ │ │ ├── GPUDeviceLostInfo.cpp │ │ │ ├── GPUDeviceLostInfo.h │ │ │ ├── GPUError.h │ │ │ ├── GPUExtent3D.h │ │ │ ├── GPUExternalTexture.h │ │ │ ├── GPUFeatures.h │ │ │ ├── GPUOrigin2D.h │ │ │ ├── GPUOrigin3D.h │ │ │ ├── GPUPipelineLayout.h │ │ │ ├── GPUQuerySet.cpp │ │ │ ├── GPUQuerySet.h │ │ │ ├── GPUQueue.cpp │ │ │ ├── GPUQueue.h │ │ │ ├── GPURenderBundle.h │ │ │ ├── GPURenderBundleEncoder.cpp │ │ │ ├── GPURenderBundleEncoder.h │ │ │ ├── GPURenderPassEncoder.cpp │ │ │ ├── GPURenderPassEncoder.h │ │ │ ├── GPURenderPipeline.cpp │ │ │ ├── GPURenderPipeline.h │ │ │ ├── GPUSampler.h │ │ │ ├── GPUShaderModule.cpp │ │ │ ├── GPUShaderModule.h │ │ │ ├── GPUSupportedLimits.cpp │ │ │ ├── GPUSupportedLimits.h │ │ │ ├── GPUTexture.cpp │ │ │ ├── GPUTexture.h │ │ │ ├── GPUTextureView.h │ │ │ ├── ImageBitmap.h │ │ │ ├── RNWebGPU.h │ │ │ └── descriptors │ │ │ ├── GPUBindGroupDescriptor.h │ │ │ ├── GPUBindGroupEntry.h │ │ │ ├── GPUBindGroupLayoutDescriptor.h │ │ │ ├── GPUBindGroupLayoutEntry.h │ │ │ ├── GPUBlendComponent.h │ │ │ ├── GPUBlendState.h │ │ │ ├── GPUBufferBinding.h │ │ │ ├── GPUBufferBindingLayout.h │ │ │ ├── GPUBufferDescriptor.h │ │ │ ├── GPUBufferUsage.h │ │ │ ├── GPUCanvasConfiguration.h │ │ │ ├── GPUColor.h │ │ │ ├── GPUColorTargetState.h │ │ │ ├── GPUColorWrite.h │ │ │ ├── GPUCommandBufferDescriptor.h │ │ │ ├── GPUCommandEncoderDescriptor.h │ │ │ ├── GPUComputePassDescriptor.h │ │ │ ├── GPUComputePassTimestampWrites.h │ │ │ ├── GPUComputePipelineDescriptor.h │ │ │ ├── GPUDepthStencilState.h │ │ │ ├── GPUDeviceDescriptor.h │ │ │ ├── GPUExternalTextureBindingLayout.h │ │ │ ├── GPUExternalTextureDescriptor.h │ │ │ ├── GPUFragmentState.h │ │ │ ├── GPUImageCopyBuffer.h │ │ │ ├── GPUImageCopyExternalImage.h │ │ │ ├── GPUImageCopyTexture.h │ │ │ ├── GPUImageCopyTextureTagged.h │ │ │ ├── GPUImageDataLayout.h │ │ │ ├── GPUMapMode.h │ │ │ ├── GPUMultisampleState.h │ │ │ ├── GPUPipelineLayoutDescriptor.h │ │ │ ├── GPUPrimitiveState.h │ │ │ ├── GPUProgrammableStage.h │ │ │ ├── GPUQuerySetDescriptor.h │ │ │ ├── GPUQueueDescriptor.h │ │ │ ├── GPURenderBundleDescriptor.h │ │ │ ├── GPURenderBundleEncoderDescriptor.h │ │ │ ├── GPURenderPassColorAttachment.h │ │ │ ├── GPURenderPassDepthStencilAttachment.h │ │ │ ├── GPURenderPassDescriptor.h │ │ │ ├── GPURenderPassTimestampWrites.h │ │ │ ├── GPURenderPipelineDescriptor.h │ │ │ ├── GPURequestAdapterOptions.h │ │ │ ├── GPUSamplerBindingLayout.h │ │ │ ├── GPUSamplerDescriptor.h │ │ │ ├── GPUShaderModuleCompilationHint.h │ │ │ ├── GPUShaderModuleDescriptor.h │ │ │ ├── GPUShaderStage.h │ │ │ ├── GPUStencilFaceState.h │ │ │ ├── GPUStorageTextureBindingLayout.h │ │ │ ├── GPUTextureBindingLayout.h │ │ │ ├── GPUTextureDescriptor.h │ │ │ ├── GPUTextureUsage.h │ │ │ ├── GPUTextureViewDescriptor.h │ │ │ ├── GPUUncapturedErrorEventInit.h │ │ │ ├── GPUVertexAttribute.h │ │ │ ├── GPUVertexBufferLayout.h │ │ │ ├── GPUVertexState.h │ │ │ └── Unions.h │ └── threading │ │ ├── CallInvokerDispatcher.h │ │ ├── Dispatcher.cpp │ │ ├── Dispatcher.h │ │ ├── ThreadPool.cpp │ │ └── ThreadPool.h │ ├── jest.config.js │ ├── package.json │ ├── react-native-wgpu.podspec │ ├── scripts │ ├── build │ │ ├── apple.toolchain.cmake │ │ ├── copy-artifacts.ts │ │ ├── dawn-configuration.ts │ │ ├── dawn.ts │ │ ├── download-artifacts.ts │ │ ├── static_build.patch │ │ └── util.ts │ └── codegen │ │ ├── Descriptors.ts │ │ ├── codegen.ts │ │ ├── model │ │ └── dawn.ts │ │ ├── templates │ │ ├── Enum.ts │ │ ├── HybridObject.ts │ │ ├── Unions.ts │ │ └── common.ts │ │ └── util.ts │ ├── src │ ├── Canvas.tsx │ ├── NativeWebGPUModule.ts │ ├── Offscreen.ts │ ├── WebGPUView.tsx │ ├── WebGPUViewNativeComponent.ts │ ├── __tests__ │ │ ├── Alpha.spec.ts │ │ ├── ArrayBuffer.spec.ts │ │ ├── Buffer.spec.ts │ │ ├── ComputeShader.spec.ts │ │ ├── Constants.spec.ts │ │ ├── Device.spec.ts │ │ ├── ExternalTexture.spec.ts │ │ ├── GPU.spec.ts │ │ ├── ImageData.spec.ts │ │ ├── Shaders.spec.ts │ │ ├── Texture.spec.ts │ │ ├── assets │ │ │ └── Di-3d.png │ │ ├── components │ │ │ ├── Wireframe │ │ │ │ ├── Shaders.ts │ │ │ │ ├── models.ts │ │ │ │ └── utils.ts │ │ │ ├── cube.ts │ │ │ ├── meshes │ │ │ │ ├── mesh.ts │ │ │ │ ├── sphere.ts │ │ │ │ ├── stanfordDragon.ts │ │ │ │ ├── stanfordDragonData.ts │ │ │ │ ├── teapot.ts │ │ │ │ └── utils.ts │ │ │ └── triangle.ts │ │ ├── config.ts │ │ ├── demos │ │ │ ├── ABuffer.spec.ts │ │ │ ├── Blur.spec.ts │ │ │ ├── Cube.spec.ts │ │ │ ├── FractalCube.spec.ts │ │ │ ├── OcclusionQuery.spec.ts │ │ │ ├── RenderBundles.spec.ts │ │ │ ├── Triangle.spec.ts │ │ │ └── Wireframe.spec.ts │ │ ├── globalSetup.ts │ │ ├── globalTeardown.ts │ │ ├── setup.ts │ │ └── snapshots │ │ │ ├── abuffer.png │ │ │ ├── asteroid.png │ │ │ ├── blur.png │ │ │ ├── buffer.png │ │ │ ├── constant-triangle.png │ │ │ ├── cube.png │ │ │ ├── f.png │ │ │ ├── f2.png │ │ │ ├── fractal-cubes.png │ │ │ ├── instanced-cubes.png │ │ │ ├── occlusion-query.png │ │ │ ├── ref.png │ │ │ ├── semi-opaque-cyan.png │ │ │ ├── texture.png │ │ │ ├── textured-cube.png │ │ │ ├── triangle-msaa.png │ │ │ ├── triangle.png │ │ │ └── two-cube.png │ ├── hooks.tsx │ └── index.tsx │ ├── tsconfig.build.json │ └── tsconfig.json ├── turbo.json └── yarn.lock /.github/actions/setup/action.yml: -------------------------------------------------------------------------------- 1 | name: Setup 2 | description: Setup Node.js and install dependencies 3 | 4 | inputs: 5 | github_token: 6 | description: 'GitHub Token' 7 | required: true 8 | 9 | runs: 10 | using: composite 11 | steps: 12 | - name: Setup Node.js 13 | uses: actions/setup-node@v3 14 | with: 15 | node-version-file: .nvmrc 16 | 17 | - name: Cache dependencies 18 | id: yarn-cache 19 | uses: actions/cache@v3 20 | with: 21 | path: | 22 | **/node_modules 23 | .yarn/install-state.gz 24 | key: ${{ runner.os }}-yarn-${{ hashFiles('yarn.lock') }}-${{ hashFiles('**/package.json', '!node_modules/**') }} 25 | restore-keys: | 26 | ${{ runner.os }}-yarn-${{ hashFiles('yarn.lock') }} 27 | ${{ runner.os }}-yarn- 28 | 29 | - name: Install dependencies 30 | if: steps.yarn-cache.outputs.cache-hit != 'true' 31 | run: yarn install --immutable 32 | shell: bash 33 | 34 | - name: Download Dawn Binary Artifacts 35 | uses: dawidd6/action-download-artifact@v2 36 | with: 37 | workflow: "build-dawn.yml" 38 | repo: wcandillon/react-native-webgpu 39 | github_token: ${{ inputs.github_token }} 40 | path: artifacts 41 | branch: main 42 | name: dawn-libs 43 | 44 | - name: Copy Artifacts to libs folder 45 | working-directory: packages/webgpu 46 | shell: bash 47 | run: yarn copy-artifacts 48 | -------------------------------------------------------------------------------- /.github/workflows/build-dawn.yml: -------------------------------------------------------------------------------- 1 | name: Build Dawn 2 | on: workflow_dispatch 3 | jobs: 4 | build: 5 | runs-on: macos-latest-large 6 | steps: 7 | - name: checkout 8 | uses: actions/checkout@v2 9 | with: 10 | submodules: true 11 | - name: Initialize Dawn's abseil-cpp submodule 12 | run: | 13 | cd externals/dawn 14 | git submodule update --init third_party/abseil-cpp 15 | - name: Setup Android NDK 16 | id: setup-ndk 17 | uses: nttld/setup-ndk@v1 18 | with: 19 | ndk-version: r26d 20 | - name: Set ANDROID_NDK 21 | run: echo "ANDROID_NDK=$ANDROID_HOME/ndk-bundle" >> $GITHUB_ENV 22 | - name: Setup Ninja 23 | uses: seanmiddleditch/gha-setup-ninja@master 24 | - uses: actions/setup-node@v3 25 | with: 26 | cache: 'yarn' 27 | cache-dependency-path: yarn.lock 28 | - name: Install Package 29 | run: yarn install --frozen-lockfile 30 | - name: Build Dawn 31 | working-directory: packages/webgpu 32 | env: 33 | ANDROID_NDK: ${{ steps.setup-ndk.outputs.ndk-path }} 34 | run: yarn build-dawn 35 | - name: Upload artifacts - Dawn Library Files 36 | if: github.ref == 'refs/heads/main' 37 | uses: actions/upload-artifact@v4 38 | with: 39 | name: dawn-libs 40 | path: | 41 | packages/webgpu/libs/dawn.json 42 | packages/webgpu/libs/android 43 | packages/webgpu/libs/apple/*.xcframework 44 | packages/webgpu/cpp/dawn 45 | packages/webgpu/cpp/webgpu 46 | -------------------------------------------------------------------------------- /.github/workflows/cpplint.yml: -------------------------------------------------------------------------------- 1 | name: cpplint 2 | on: 3 | push: 4 | branches: 5 | - main 6 | pull_request: 7 | jobs: 8 | cpplint: 9 | runs-on: ubuntu-latest 10 | steps: 11 | - uses: actions/checkout@v1 12 | - uses: actions/setup-python@v1 13 | - run: pip install cpplint 14 | - run: cpplint --linelength=230 --filter=-legal/copyright,-whitespace/indent,-whitespace/comments,-whitespace/ending_newline,-build/include_order,-runtime/references,-readability/todo,-whitespace/blank_line,-whitespace/todo,-runtime/int,-build/c++11,-whitespace/parens --exclude=package/example --exclude=package/android/.cxx --exclude=package/cpp/webgpu --exclude=package/cpp/dawn --exclude=package/ios --exclude=package/android/build --exclude=package/node_modules --recursive package 15 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | !packages/webgpu/scripts/build 2 | # Yarn 3 | .package/.yarn/* 4 | .yarn/* 5 | !.yarn/patches 6 | !.yarn/plugins 7 | !.yarn/releases 8 | !.yarn/sdks 9 | !.yarn/versions 10 | 11 | #apps/*/ios 12 | #apps/*/android 13 | 14 | # OSX 15 | # 16 | .DS_Store 17 | 18 | # node.js 19 | # 20 | node_modules/ 21 | npm-debug.log 22 | yarn-error.log 23 | .eslintcache 24 | 25 | # Xcode 26 | # 27 | build 28 | *.pbxuser 29 | !default.pbxuser 30 | *.mode1v3 31 | !default.mode1v3 32 | *.mode2v3 33 | !default.mode2v3 34 | *.perspectivev3 35 | !default.perspectivev3 36 | xcuserdata 37 | *.xccheckout 38 | *.moved-aside 39 | DerivedData 40 | *.hmap 41 | *.ipa 42 | *.xcuserstate 43 | project.xcworkspace 44 | 45 | # Android/IntelliJ 46 | build 47 | .idea 48 | .gradle 49 | local.properties 50 | *.iml 51 | .cxx 52 | # Legacy Eclipse Settings 53 | .settings/ 54 | 55 | # BUCK 56 | buck-out/ 57 | \.buckd/ 58 | *.keystore 59 | 60 | # Build 61 | dist 62 | package/lib 63 | .vscode 64 | *.tgz 65 | 66 | 67 | # Externals 68 | packages/webgpu/libs 69 | packages/webgpu/cpp/dawn/ 70 | packages/webgpu/cpp/webgpu/ 71 | packages/webgpu/lib 72 | !packages/webgpu/scripts/build 73 | artifacts/ 74 | 75 | 76 | # Cocoapods 77 | # 78 | apps/example/**/Pods 79 | # Ruby 80 | apps/vendor/ 81 | 82 | .turbo 83 | -------------------------------------------------------------------------------- /.gitmodules: -------------------------------------------------------------------------------- 1 | [submodule "externals/dawn"] 2 | path = externals/dawn 3 | url = https://dawn.googlesource.com/dawn 4 | branch = chromium/7213 5 | -------------------------------------------------------------------------------- /.nvmrc: -------------------------------------------------------------------------------- 1 | v22.3.0 2 | -------------------------------------------------------------------------------- /.yarn/patches/@react-three-fiber-npm-8.17.6-bc537e834c.patch: -------------------------------------------------------------------------------- 1 | diff --git a/package.json b/package.json 2 | index e866692ead26f118141e8a3c67374a09f8aab0e9..08997ecbf59a077d15d035aee4f1285a5da76a95 100644 3 | --- a/package.json 4 | +++ b/package.json 5 | @@ -30,7 +30,7 @@ 6 | "main": "dist/react-three-fiber.cjs.js", 7 | "module": "dist/react-three-fiber.esm.js", 8 | "types": "dist/react-three-fiber.cjs.d.ts", 9 | - "react-native": "native/dist/react-three-fiber-native.cjs.js", 10 | + "react-native": "dist/react-three-fiber.cjs.js", 11 | "sideEffects": false, 12 | "preconstruct": { 13 | "entrypoints": [ 14 | -------------------------------------------------------------------------------- /.yarnrc.yml: -------------------------------------------------------------------------------- 1 | nodeLinker: node-modules 2 | 3 | yarnPath: .yarn/releases/yarn-3.6.4.cjs 4 | -------------------------------------------------------------------------------- /LICENSE.md: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright 2024-present, William Candillon. 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. -------------------------------------------------------------------------------- /apps/example/.eslintrc: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "react-native-wcandillon", 3 | "ignorePatterns": ["**/*/components/meshes", "**/Pods/**"], 4 | "rules": { 5 | "no-bitwise": "off", 6 | "@typescript-eslint/no-require-imports": "off", 7 | "prettier/prettier": [ 8 | "error", 9 | { 10 | "trailingComma": "all" 11 | } 12 | ] 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /apps/example/.gitignore: -------------------------------------------------------------------------------- 1 | *.binlog 2 | *.hprof 3 | *.xcworkspace/ 4 | *.zip 5 | .DS_Store 6 | .gradle/ 7 | .idea/ 8 | .vs/ 9 | .xcode.env 10 | **/Pods/** 11 | build/ 12 | dist/* 13 | !dist/.gitignore 14 | local.properties 15 | msbuild.binlog 16 | node_modules/ 17 | -------------------------------------------------------------------------------- /apps/example/.watchmanconfig: -------------------------------------------------------------------------------- 1 | {} 2 | -------------------------------------------------------------------------------- /apps/example/android/build.gradle: -------------------------------------------------------------------------------- 1 | buildscript { 2 | apply(from: { 3 | def searchDir = rootDir.toPath() 4 | do { 5 | def p = searchDir.resolve("node_modules/react-native-test-app/android/dependencies.gradle") 6 | if (p.toFile().exists()) { 7 | return p.toRealPath().toString() 8 | } 9 | } while (searchDir = searchDir.getParent()) 10 | throw new GradleException("Could not find `react-native-test-app`") 11 | }()) 12 | 13 | repositories { 14 | mavenCentral() 15 | google() 16 | } 17 | 18 | dependencies { 19 | getReactNativeDependencies().each { dependency -> 20 | classpath(dependency) 21 | } 22 | } 23 | } 24 | 25 | allprojects { 26 | repositories { 27 | maven { 28 | // All of React Native (JS, Obj-C sources, Android binaries) is installed from npm 29 | url({ 30 | def searchDir = rootDir.toPath() 31 | do { 32 | def p = searchDir.resolve("node_modules/react-native/android") 33 | if (p.toFile().exists()) { 34 | return p.toRealPath().toString() 35 | } 36 | } while (searchDir = searchDir.getParent()) 37 | throw new GradleException("Could not find `react-native`") 38 | }()) 39 | } 40 | mavenCentral() 41 | google() 42 | } 43 | } 44 | -------------------------------------------------------------------------------- /apps/example/android/gradle/wrapper/gradle-wrapper.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wcandillon/react-native-webgpu/a6dbc83a14784a37a1d3b7ce57b839c70b479d2f/apps/example/android/gradle/wrapper/gradle-wrapper.jar -------------------------------------------------------------------------------- /apps/example/android/gradle/wrapper/gradle-wrapper.properties: -------------------------------------------------------------------------------- 1 | distributionBase=GRADLE_USER_HOME 2 | distributionPath=wrapper/dists 3 | distributionUrl=https\://services.gradle.org/distributions/gradle-8.13-bin.zip 4 | networkTimeout=10000 5 | validateDistributionUrl=true 6 | zipStoreBase=GRADLE_USER_HOME 7 | zipStorePath=wrapper/dists 8 | -------------------------------------------------------------------------------- /apps/example/android/settings.gradle: -------------------------------------------------------------------------------- 1 | pluginManagement { 2 | repositories { 3 | gradlePluginPortal() 4 | mavenCentral() 5 | google() 6 | } 7 | } 8 | 9 | rootProject.name = "Example" 10 | 11 | apply(from: { 12 | def searchDir = rootDir.toPath() 13 | do { 14 | def p = searchDir.resolve("node_modules/react-native-test-app/test-app.gradle") 15 | if (p.toFile().exists()) { 16 | return p.toRealPath().toString() 17 | } 18 | } while (searchDir = searchDir.getParent()) 19 | throw new GradleException("Could not find `react-native-test-app`") 20 | }()) 21 | applyTestAppSettings(settings) 22 | -------------------------------------------------------------------------------- /apps/example/app.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "Example", 3 | "displayName": "Example", 4 | "singleApp": "example-app", 5 | "components": [ 6 | { 7 | "appKey": "Example", 8 | "displayName": "Example", 9 | "slug": "example-app" 10 | } 11 | ], 12 | "resources": { 13 | "android": [ 14 | "dist/res" 15 | ], 16 | "ios": [ 17 | "dist/assets", 18 | "dist/main.ios.jsbundle" 19 | ], 20 | "macos": [ 21 | "dist/assets", 22 | "dist/main.macos.jsbundle" 23 | ], 24 | "visionos": [ 25 | "dist/assets", 26 | "dist/main.visionos.jsbundle" 27 | ] 28 | }, 29 | "ios": { 30 | "metalAPIValidation": false 31 | }, 32 | "macos": { 33 | "metalAPIValidation": false 34 | }, 35 | "visionos": { 36 | "metalAPIValidation": false 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /apps/example/babel.config.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | presets: ['module:@react-native/babel-preset'], 3 | plugins: [ 4 | 'react-native-reanimated/plugin' 5 | ], 6 | }; 7 | -------------------------------------------------------------------------------- /apps/example/index.js: -------------------------------------------------------------------------------- 1 | /** 2 | * @format 3 | */ 4 | 5 | import {AppRegistry} from 'react-native'; 6 | import App from './src/App'; 7 | import {name as appName} from './app.json'; 8 | 9 | AppRegistry.registerComponent(appName, () => App); 10 | -------------------------------------------------------------------------------- /apps/example/ios/Podfile: -------------------------------------------------------------------------------- 1 | ws_dir = Pathname.new(__dir__) 2 | ws_dir = ws_dir.parent until 3 | File.exist?("#{ws_dir}/node_modules/react-native-test-app/test_app.rb") || 4 | ws_dir.expand_path.to_s == '/' 5 | require "#{ws_dir}/node_modules/react-native-test-app/test_app.rb" 6 | 7 | workspace 'Example.xcworkspace' 8 | 9 | options = { 10 | :hermes_enabled => true, 11 | :fabric_enabled => true, 12 | :new_arch_enabled => true 13 | } 14 | 15 | use_test_app! options 16 | -------------------------------------------------------------------------------- /apps/example/jest.config.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | preset: 'react-native', 3 | }; 4 | -------------------------------------------------------------------------------- /apps/example/macos/Podfile: -------------------------------------------------------------------------------- 1 | ws_dir = Pathname.new(__dir__) 2 | ws_dir = ws_dir.parent until 3 | File.exist?("#{ws_dir}/node_modules/react-native-test-app/macos/test_app.rb") || 4 | ws_dir.expand_path.to_s == '/' 5 | require "#{ws_dir}/node_modules/react-native-test-app/macos/test_app.rb" 6 | 7 | workspace 'Example.xcworkspace' 8 | 9 | use_test_app! 10 | -------------------------------------------------------------------------------- /apps/example/metro.config.js: -------------------------------------------------------------------------------- 1 | const { makeMetroConfig } = require("@rnx-kit/metro-config"); 2 | const path = require('path'); 3 | 4 | const root = path.resolve(__dirname, '../..'); 5 | const threePackagePath = path.resolve(root, 'node_modules/three'); 6 | 7 | const extraConfig = { 8 | watchFolders: [root], 9 | resolver: { 10 | extraNodeModules: { 11 | 'three': threePackagePath, 12 | }, 13 | resolveRequest: (context, moduleName, platform) => { 14 | if (moduleName.startsWith('three/addons/')) { 15 | return { 16 | filePath: path.resolve(threePackagePath, 'examples/jsm/' + moduleName.replace('three/addons/', '') + '.js'), 17 | type: 'sourceFile', 18 | }; 19 | } 20 | if (moduleName === 'three' || moduleName === 'three/webgpu') { 21 | return { 22 | filePath: path.resolve(threePackagePath, 'build/three.webgpu.js'), 23 | type: 'sourceFile', 24 | }; 25 | } 26 | if (moduleName === 'three/tsl') { 27 | return { 28 | filePath: path.resolve(threePackagePath, 'build/three.tsl.js'), 29 | type: 'sourceFile', 30 | }; 31 | } 32 | // Let Metro handle other modules 33 | return context.resolveRequest(context, moduleName, platform); 34 | }, 35 | }, 36 | 37 | transformer: { 38 | getTransformOptions: async () => ({ 39 | transform: { 40 | experimentalImportSupport: false, 41 | inlineRequires: true, 42 | }, 43 | }), 44 | }, 45 | }; 46 | 47 | const metroConfig = makeMetroConfig(extraConfig); 48 | metroConfig.resolver.assetExts.push('glb', 'gltf', 'jpg', 'bin', 'hdr'); 49 | 50 | 51 | module.exports = metroConfig; 52 | -------------------------------------------------------------------------------- /apps/example/react-native.config.js: -------------------------------------------------------------------------------- 1 | const project = (() => { 2 | try { 3 | const { configureProjects } = require("react-native-test-app"); 4 | return configureProjects({ 5 | android: { 6 | sourceDir: "android", 7 | packageName: "com.microsoft.reacttestapp" 8 | }, 9 | ios: { 10 | sourceDir: "ios", 11 | }, 12 | windows: { 13 | sourceDir: "windows", 14 | solutionFile: "windows/example.sln", 15 | }, 16 | }); 17 | } catch (_) { 18 | return undefined; 19 | } 20 | })(); 21 | 22 | module.exports = { 23 | ...(project ? { project } : undefined), 24 | }; -------------------------------------------------------------------------------- /apps/example/src/ABuffer/index.ts: -------------------------------------------------------------------------------- 1 | export * from "./ABuffer"; 2 | -------------------------------------------------------------------------------- /apps/example/src/CanvasAPI/index.ts: -------------------------------------------------------------------------------- 1 | export * from "./CanvasAPI"; 2 | -------------------------------------------------------------------------------- /apps/example/src/ComputeBoids/index.ts: -------------------------------------------------------------------------------- 1 | export * from "./ComputeBoids"; 2 | -------------------------------------------------------------------------------- /apps/example/src/Cube/index.ts: -------------------------------------------------------------------------------- 1 | export * from "./Cube"; 2 | export * from "./TexturedCube"; 3 | export * from "./FractalCube"; 4 | export * from "./InstancedCube"; 5 | export * from "./Cubemap"; 6 | -------------------------------------------------------------------------------- /apps/example/src/GradientTiles/gradientWgsl.ts: -------------------------------------------------------------------------------- 1 | export const vertWGSL = ` 2 | struct Output { 3 | @builtin(position) pos: vec4f, 4 | @location(0) uv: vec2f, 5 | } 6 | 7 | @vertex 8 | fn vert( 9 | @builtin(vertex_index) vertexIndex: u32, 10 | ) -> Output { 11 | var pos = array( 12 | vec2(1, 1), // top-right 13 | vec2(-1, 1), // top-left 14 | vec2(1, -1), // bottom-right 15 | vec2(-1, -1) // bottom-left 16 | ); 17 | 18 | var uv = array( 19 | vec2(1., 1.), // top-right 20 | vec2(0., 1.), // top-left 21 | vec2(1., 0.), // bottom-right 22 | vec2(0., 0.) // bottom-left 23 | ); 24 | 25 | var out: Output; 26 | out.pos = vec4f(pos[vertexIndex], 0.0, 1.0); 27 | out.uv = uv[vertexIndex]; 28 | return out; 29 | }`; 30 | 31 | export const fragWGSL = ` 32 | @fragment 33 | fn frag( 34 | @location(0) uv: vec2f, 35 | ) -> @location(0) vec4f { 36 | let red = floor(uv.x * f32(_EXT_.span.x)) / f32(_EXT_.span.x); 37 | let green = floor(uv.y * f32(_EXT_.span.y)) / f32(_EXT_.span.y); 38 | return vec4(red, green, 0.5, 1.0); 39 | }`; 40 | -------------------------------------------------------------------------------- /apps/example/src/GradientTiles/index.ts: -------------------------------------------------------------------------------- 1 | export * from "./GradientTiles"; 2 | -------------------------------------------------------------------------------- /apps/example/src/MNISTInference/index.ts: -------------------------------------------------------------------------------- 1 | export * from "./MNISTInference"; 2 | -------------------------------------------------------------------------------- /apps/example/src/OcclusionQuery/index.ts: -------------------------------------------------------------------------------- 1 | export * from "./OcclusionQuery"; 2 | -------------------------------------------------------------------------------- /apps/example/src/Particles/index.ts: -------------------------------------------------------------------------------- 1 | export * from "./Particles"; 2 | -------------------------------------------------------------------------------- /apps/example/src/RenderBundles/index.ts: -------------------------------------------------------------------------------- 1 | export * from "./RenderBundles"; 2 | -------------------------------------------------------------------------------- /apps/example/src/Resize/index.ts: -------------------------------------------------------------------------------- 1 | export * from "./Resize"; 2 | -------------------------------------------------------------------------------- /apps/example/src/ReversedZ/index.ts: -------------------------------------------------------------------------------- 1 | export * from "./ReversedZ"; 2 | -------------------------------------------------------------------------------- /apps/example/src/Route.ts: -------------------------------------------------------------------------------- 1 | export type Routes = { 2 | Home: undefined; 3 | HelloTriangle: undefined; 4 | HelloTriangleMSAA: undefined; 5 | Cube: undefined; 6 | ThreeJS: undefined; 7 | Tensorflow: undefined; 8 | InstancedCube: undefined; 9 | TexturedCube: undefined; 10 | FractalCube: undefined; 11 | Cubemap: undefined; 12 | SamplerParameters: undefined; 13 | RenderBundles: undefined; 14 | OcclusionQuery: undefined; 15 | ComputeBoids: undefined; 16 | MNISTInference: undefined; 17 | ABuffer: undefined; 18 | Particles: undefined; 19 | ShadowMapping: undefined; 20 | DeferedRendering: undefined; 21 | ReversedZ: undefined; 22 | Wireframe: undefined; 23 | Resize: undefined; 24 | Tests: undefined; 25 | GradientTiles: undefined; 26 | CanvasAPI: undefined; 27 | }; 28 | -------------------------------------------------------------------------------- /apps/example/src/Sampler/index.ts: -------------------------------------------------------------------------------- 1 | export * from "./SamplerParameters"; 2 | -------------------------------------------------------------------------------- /apps/example/src/ShadowMapping/index.ts: -------------------------------------------------------------------------------- 1 | export * from "./ShadowMapping"; 2 | export * from "./DeferedRendering"; 3 | -------------------------------------------------------------------------------- /apps/example/src/Tensorflow/Platform.ts: -------------------------------------------------------------------------------- 1 | import type { Platform } from "@tensorflow/tfjs-core"; 2 | import type { RequestDetails } from "@tensorflow/tfjs-core/dist/io/types"; 3 | 4 | export class PlatformReactNative implements Platform { 5 | fetch(path: string, init?: RequestInit, _options?: RequestDetails) { 6 | return fetch(path, init); 7 | } 8 | 9 | encode(text: string, encoding: BufferEncoding) { 10 | return new Uint8Array(Buffer.from(text, encoding)); 11 | } 12 | 13 | decode(bytes: Uint8Array, encoding: BufferEncoding) { 14 | return Buffer.from(bytes).toString(encoding); 15 | } 16 | 17 | now() { 18 | return Date.now(); 19 | } 20 | 21 | setTimeoutCustom() { 22 | throw new Error("react native does not support setTimeoutCustom"); 23 | } 24 | 25 | isTypedArray( 26 | a: unknown, 27 | ): a is Uint8Array | Uint8ClampedArray | Int32Array | Float32Array { 28 | return ( 29 | a instanceof Float32Array || 30 | a instanceof Int32Array || 31 | a instanceof Uint8Array || 32 | a instanceof Uint8ClampedArray 33 | ); 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /apps/example/src/Tensorflow/index.ts: -------------------------------------------------------------------------------- 1 | export * from "./Tensorflow"; 2 | -------------------------------------------------------------------------------- /apps/example/src/ThreeJS/Cube.tsx: -------------------------------------------------------------------------------- 1 | import * as THREE from "three"; 2 | import { Canvas, useCanvasEffect } from "react-native-wgpu"; 3 | import { View } from "react-native"; 4 | 5 | import { makeWebGPURenderer } from "./components/makeWebGPURenderer"; 6 | 7 | export const Cube = () => { 8 | const ref = useCanvasEffect(async () => { 9 | const context = ref.current!.getContext("webgpu")!; 10 | const { width, height } = context.canvas; 11 | 12 | const camera = new THREE.PerspectiveCamera(70, width / height, 0.01, 10); 13 | camera.position.z = 1; 14 | 15 | const scene = new THREE.Scene(); 16 | 17 | const geometry = new THREE.BoxGeometry(0.2, 0.2, 0.2); 18 | const material = new THREE.MeshNormalMaterial(); 19 | 20 | const mesh = new THREE.Mesh(geometry, material); 21 | scene.add(mesh); 22 | 23 | const renderer = makeWebGPURenderer(context); 24 | await renderer.init(); 25 | 26 | function animate(time: number) { 27 | mesh.rotation.x = time / 2000; 28 | mesh.rotation.y = time / 1000; 29 | 30 | renderer.render(scene, camera); 31 | context.present(); 32 | } 33 | renderer.setAnimationLoop(animate); 34 | return () => { 35 | renderer.setAnimationLoop(null); 36 | }; 37 | }); 38 | 39 | return ( 40 | 41 | 42 | 43 | ); 44 | }; 45 | -------------------------------------------------------------------------------- /apps/example/src/ThreeJS/Helmet.tsx: -------------------------------------------------------------------------------- 1 | import * as THREE from "three"; 2 | import { Canvas, useGPUContext } from "react-native-wgpu"; 3 | import { StyleSheet, Text, View } from "react-native"; 4 | import { useEffect } from "react"; 5 | 6 | import { useGLTF, useRGBE } from "./assets/AssetManager"; 7 | import { makeWebGPURenderer } from "./components/makeWebGPURenderer"; 8 | 9 | export const Helmet = () => { 10 | const texture = useRGBE(require("./assets/helmet/royal_esplanade_1k.hdr")); 11 | const gltf = useGLTF(require("./assets/helmet/DamagedHelmet.gltf")); 12 | const { ref, context } = useGPUContext(); 13 | useEffect(() => { 14 | if (!texture || !gltf || !context) { 15 | return; 16 | } 17 | const { width, height } = context.canvas; 18 | 19 | const clock = new THREE.Clock(); 20 | 21 | const camera = new THREE.PerspectiveCamera(45, width / height, 0.25, 20); 22 | camera.position.set(-1.8, 0.6, 2.7); 23 | 24 | const scene = new THREE.Scene(); 25 | 26 | const renderer = makeWebGPURenderer(context); 27 | 28 | renderer.toneMapping = THREE.ACESFilmicToneMapping; 29 | 30 | texture.mapping = THREE.EquirectangularReflectionMapping; 31 | 32 | scene.background = texture; 33 | scene.environment = texture; 34 | 35 | scene.add(gltf.scene); 36 | renderer.setAnimationLoop(animate); 37 | 38 | // 39 | function animateCamera() { 40 | const elapsed = clock.getElapsedTime(); 41 | const distance = 5; 42 | camera.position.x = Math.sin(elapsed) * distance; 43 | camera.position.z = Math.cos(elapsed) * distance; 44 | camera.lookAt(new THREE.Vector3(0, 0, 0)); 45 | } 46 | 47 | function animate() { 48 | animateCamera(); 49 | renderer.render(scene, camera); 50 | context!.present(); 51 | } 52 | 53 | return () => { 54 | renderer.setAnimationLoop(null); 55 | }; 56 | }, [texture, gltf, context]); 57 | 58 | return ( 59 | 60 | Loading assets... 61 | 62 | 63 | 64 | 65 | ); 66 | }; 67 | -------------------------------------------------------------------------------- /apps/example/src/ThreeJS/List.tsx: -------------------------------------------------------------------------------- 1 | import * as React from "react"; 2 | import { ScrollView, StyleSheet, Text, View } from "react-native"; 3 | import { useNavigation } from "@react-navigation/native"; 4 | import { RectButton } from "react-native-gesture-handler"; 5 | import type { StackNavigationProp } from "@react-navigation/stack"; 6 | 7 | import type { Routes } from "./Routes"; 8 | 9 | export const examples = [ 10 | { 11 | screen: "Cube", 12 | title: "🧊 Cube", 13 | }, 14 | { 15 | screen: "InstancedMesh", 16 | title: "🐵 Instanced Mesh", 17 | }, 18 | { 19 | screen: "Backdrop", 20 | title: "💃🏿 Backdrop", 21 | }, 22 | { 23 | screen: "Helmet", 24 | title: "⛑️ Helmet", 25 | }, 26 | { 27 | screen: "PostProcessing", 28 | title: "🪄 Post Processing Effects", 29 | }, 30 | { 31 | screen: "Fiber", 32 | title: "👕 Fiber", 33 | }, 34 | ] as const; 35 | 36 | const styles = StyleSheet.create({ 37 | container: {}, 38 | content: { 39 | paddingBottom: 32, 40 | }, 41 | thumbnail: { 42 | backgroundColor: "white", 43 | padding: 32, 44 | borderBottomWidth: StyleSheet.hairlineWidth, 45 | }, 46 | title: {}, 47 | }); 48 | 49 | export const List = () => { 50 | const { navigate } = useNavigation>(); 51 | return ( 52 | 53 | {examples.map((thumbnail) => ( 54 | navigate(thumbnail.screen)} 57 | > 58 | 59 | {thumbnail.title} 60 | 61 | 62 | ))} 63 | 64 | ); 65 | }; 66 | -------------------------------------------------------------------------------- /apps/example/src/ThreeJS/Routes.ts: -------------------------------------------------------------------------------- 1 | export type Routes = { 2 | List: undefined; 3 | Cube: undefined; 4 | Helmet: undefined; 5 | Backdrop: undefined; 6 | InstancedMesh: undefined; 7 | Fiber: undefined; 8 | PostProcessing: undefined; 9 | }; 10 | -------------------------------------------------------------------------------- /apps/example/src/ThreeJS/assets/PrimaryIonDrive.glb: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wcandillon/react-native-webgpu/a6dbc83a14784a37a1d3b7ce57b839c70b479d2f/apps/example/src/ThreeJS/assets/PrimaryIonDrive.glb -------------------------------------------------------------------------------- /apps/example/src/ThreeJS/assets/helmet/DamagedHelmet.bin: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wcandillon/react-native-webgpu/a6dbc83a14784a37a1d3b7ce57b839c70b479d2f/apps/example/src/ThreeJS/assets/helmet/DamagedHelmet.bin -------------------------------------------------------------------------------- /apps/example/src/ThreeJS/assets/helmet/Default_AO.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wcandillon/react-native-webgpu/a6dbc83a14784a37a1d3b7ce57b839c70b479d2f/apps/example/src/ThreeJS/assets/helmet/Default_AO.jpg -------------------------------------------------------------------------------- /apps/example/src/ThreeJS/assets/helmet/Default_albedo.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wcandillon/react-native-webgpu/a6dbc83a14784a37a1d3b7ce57b839c70b479d2f/apps/example/src/ThreeJS/assets/helmet/Default_albedo.jpg -------------------------------------------------------------------------------- /apps/example/src/ThreeJS/assets/helmet/Default_emissive.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wcandillon/react-native-webgpu/a6dbc83a14784a37a1d3b7ce57b839c70b479d2f/apps/example/src/ThreeJS/assets/helmet/Default_emissive.jpg -------------------------------------------------------------------------------- /apps/example/src/ThreeJS/assets/helmet/Default_metalRoughness.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wcandillon/react-native-webgpu/a6dbc83a14784a37a1d3b7ce57b839c70b479d2f/apps/example/src/ThreeJS/assets/helmet/Default_metalRoughness.jpg -------------------------------------------------------------------------------- /apps/example/src/ThreeJS/assets/helmet/Default_normal.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wcandillon/react-native-webgpu/a6dbc83a14784a37a1d3b7ce57b839c70b479d2f/apps/example/src/ThreeJS/assets/helmet/Default_normal.jpg -------------------------------------------------------------------------------- /apps/example/src/ThreeJS/assets/helmet/royal_esplanade_1k.hdr: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wcandillon/react-native-webgpu/a6dbc83a14784a37a1d3b7ce57b839c70b479d2f/apps/example/src/ThreeJS/assets/helmet/royal_esplanade_1k.hdr -------------------------------------------------------------------------------- /apps/example/src/ThreeJS/assets/michelle/Ch03_1001_Diffuse.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wcandillon/react-native-webgpu/a6dbc83a14784a37a1d3b7ce57b839c70b479d2f/apps/example/src/ThreeJS/assets/michelle/Ch03_1001_Diffuse.png -------------------------------------------------------------------------------- /apps/example/src/ThreeJS/assets/michelle/Ch03_1001_Glossiness.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wcandillon/react-native-webgpu/a6dbc83a14784a37a1d3b7ce57b839c70b479d2f/apps/example/src/ThreeJS/assets/michelle/Ch03_1001_Glossiness.png -------------------------------------------------------------------------------- /apps/example/src/ThreeJS/assets/michelle/Ch03_1001_Normal.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wcandillon/react-native-webgpu/a6dbc83a14784a37a1d3b7ce57b839c70b479d2f/apps/example/src/ThreeJS/assets/michelle/Ch03_1001_Normal.png -------------------------------------------------------------------------------- /apps/example/src/ThreeJS/assets/michelle/model.bin: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wcandillon/react-native-webgpu/a6dbc83a14784a37a1d3b7ce57b839c70b479d2f/apps/example/src/ThreeJS/assets/michelle/model.bin -------------------------------------------------------------------------------- /apps/example/src/ThreeJS/assets/scene.bin: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wcandillon/react-native-webgpu/a6dbc83a14784a37a1d3b7ce57b839c70b479d2f/apps/example/src/ThreeJS/assets/scene.bin -------------------------------------------------------------------------------- /apps/example/src/ThreeJS/assets/textures/uv_grid_opengl.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wcandillon/react-native-webgpu/a6dbc83a14784a37a1d3b7ce57b839c70b479d2f/apps/example/src/ThreeJS/assets/textures/uv_grid_opengl.jpg -------------------------------------------------------------------------------- /apps/example/src/ThreeJS/components/makeWebGPURenderer.ts: -------------------------------------------------------------------------------- 1 | import type { NativeCanvas } from "react-native-wgpu"; 2 | import * as THREE from "three"; 3 | 4 | // Here we need to wrap the Canvas into a non-host object for now 5 | export class ReactNativeCanvas { 6 | constructor(private canvas: NativeCanvas) {} 7 | 8 | get width() { 9 | return this.canvas.width; 10 | } 11 | 12 | get height() { 13 | return this.canvas.height; 14 | } 15 | 16 | set width(width: number) { 17 | this.canvas.width = width; 18 | } 19 | 20 | set height(height: number) { 21 | this.canvas.height = height; 22 | } 23 | 24 | get clientWidth() { 25 | return this.canvas.width; 26 | } 27 | 28 | get clientHeight() { 29 | return this.canvas.height; 30 | } 31 | 32 | set clientWidth(width: number) { 33 | this.canvas.width = width; 34 | } 35 | 36 | set clientHeight(height: number) { 37 | this.canvas.height = height; 38 | } 39 | 40 | addEventListener(_type: string, _listener: EventListener) { 41 | // TODO 42 | } 43 | 44 | removeEventListener(_type: string, _listener: EventListener) { 45 | // TODO 46 | } 47 | 48 | dispatchEvent(_event: Event) { 49 | // TODO 50 | } 51 | 52 | setPointerCapture() { 53 | // TODO 54 | } 55 | 56 | releasePointerCapture() { 57 | // TODO 58 | } 59 | } 60 | 61 | export const makeWebGPURenderer = ( 62 | context: GPUCanvasContext, 63 | { antialias = true }: { antialias?: boolean } = {}, 64 | ) => 65 | new THREE.WebGPURenderer({ 66 | antialias, 67 | // eslint-disable-next-line @typescript-eslint/ban-ts-comment 68 | // @ts-expect-error 69 | canvas: new ReactNativeCanvas(context.canvas), 70 | context, 71 | }); 72 | -------------------------------------------------------------------------------- /apps/example/src/ThreeJS/index.tsx: -------------------------------------------------------------------------------- 1 | import React, { useEffect } from "react"; 2 | import { createStackNavigator } from "@react-navigation/stack"; 3 | import { warnIfNotHardwareAccelerated } from "react-native-wgpu"; 4 | 5 | import { Cube } from "./Cube"; 6 | import type { Routes } from "./Routes"; 7 | import { List } from "./List"; 8 | import { Helmet } from "./Helmet"; 9 | import { Backdrop } from "./Backdrop"; 10 | import { InstancedMesh } from "./InstancedMesh"; 11 | import { Fiber } from "./Fiber"; 12 | import { PostProcessing } from "./PostProcessing"; 13 | 14 | const Stack = createStackNavigator(); 15 | export const ThreeJS = () => { 16 | useEffect(() => { 17 | navigator.gpu.requestAdapter().then((adapter) => { 18 | if (adapter) { 19 | warnIfNotHardwareAccelerated(adapter); 20 | } 21 | }); 22 | }, []); 23 | return ( 24 | 25 | null, 31 | }} 32 | /> 33 | 40 | 47 | 54 | 61 | 68 | 75 | 76 | ); 77 | }; 78 | -------------------------------------------------------------------------------- /apps/example/src/Triangle/index.ts: -------------------------------------------------------------------------------- 1 | export * from "./HelloTriangle"; 2 | export * from "./HelloTriangleMSAA"; 3 | -------------------------------------------------------------------------------- /apps/example/src/Triangle/triangle.ts: -------------------------------------------------------------------------------- 1 | export const triangleVertWGSL = `@vertex 2 | fn main( 3 | @builtin(vertex_index) VertexIndex : u32 4 | ) -> @builtin(position) vec4f { 5 | var pos = array( 6 | vec2(0.0, 0.5), 7 | vec2(-0.5, -0.5), 8 | vec2(0.5, -0.5) 9 | ); 10 | 11 | return vec4f(pos[VertexIndex], 0.0, 1.0); 12 | }`; 13 | 14 | export const redFragWGSL = `@fragment 15 | fn main() -> @location(0) vec4f { 16 | return vec4(1.0, 0.0, 0.0, 1.0); 17 | }`; 18 | -------------------------------------------------------------------------------- /apps/example/src/Wireframe/index.ts: -------------------------------------------------------------------------------- 1 | export * from "./Wireframe"; 2 | -------------------------------------------------------------------------------- /apps/example/src/Wireframe/utils.ts: -------------------------------------------------------------------------------- 1 | export function rand(min?: number, max?: number) { 2 | if (min === undefined) { 3 | max = 1; 4 | min = 0; 5 | } else if (max === undefined) { 6 | max = min; 7 | min = 0; 8 | } 9 | return Math.random() * (max - min) + min; 10 | } 11 | 12 | export function randInt(min: number, max?: number) { 13 | return Math.floor(rand(min, max)); 14 | } 15 | 16 | export function randColor() { 17 | return [rand(), rand(), rand(), 1]; 18 | } 19 | 20 | export function randElement(arr: T[]): T { 21 | return arr[randInt(arr.length)]; 22 | } 23 | -------------------------------------------------------------------------------- /apps/example/src/assets/Di-3d.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wcandillon/react-native-webgpu/a6dbc83a14784a37a1d3b7ce57b839c70b479d2f/apps/example/src/assets/Di-3d.png -------------------------------------------------------------------------------- /apps/example/src/assets/cubemap/credit.txt: -------------------------------------------------------------------------------- 1 | Cubemap image available under a Creative Commons Attribution 3.0 Unported License at https://www.humus.name/index.php?page=Textures&ID=58 2 | -------------------------------------------------------------------------------- /apps/example/src/assets/cubemap/negx.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wcandillon/react-native-webgpu/a6dbc83a14784a37a1d3b7ce57b839c70b479d2f/apps/example/src/assets/cubemap/negx.jpg -------------------------------------------------------------------------------- /apps/example/src/assets/cubemap/negy.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wcandillon/react-native-webgpu/a6dbc83a14784a37a1d3b7ce57b839c70b479d2f/apps/example/src/assets/cubemap/negy.jpg -------------------------------------------------------------------------------- /apps/example/src/assets/cubemap/negz.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wcandillon/react-native-webgpu/a6dbc83a14784a37a1d3b7ce57b839c70b479d2f/apps/example/src/assets/cubemap/negz.jpg -------------------------------------------------------------------------------- /apps/example/src/assets/cubemap/posx.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wcandillon/react-native-webgpu/a6dbc83a14784a37a1d3b7ce57b839c70b479d2f/apps/example/src/assets/cubemap/posx.jpg -------------------------------------------------------------------------------- /apps/example/src/assets/cubemap/posy.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wcandillon/react-native-webgpu/a6dbc83a14784a37a1d3b7ce57b839c70b479d2f/apps/example/src/assets/cubemap/posy.jpg -------------------------------------------------------------------------------- /apps/example/src/assets/cubemap/posz.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wcandillon/react-native-webgpu/a6dbc83a14784a37a1d3b7ce57b839c70b479d2f/apps/example/src/assets/cubemap/posz.jpg -------------------------------------------------------------------------------- /apps/example/src/assets/cubemap/readme.txt: -------------------------------------------------------------------------------- 1 | Author 2 | ====== 3 | 4 | This is the work of Emil Persson, aka Humus. 5 | http://www.humus.name 6 | humus@comhem.se 7 | 8 | 9 | 10 | Legal stuff 11 | =========== 12 | 13 | This work is free and may be used by anyone for any purpose 14 | and may be distributed freely to anyone using any distribution 15 | media or distribution method as long as this file is included. 16 | Distribution without this file is allowed if it's distributed 17 | with free non-commercial software; however, fair credit of the 18 | original author is expected. 19 | Any commercial distribution of this software requires the written 20 | approval of Emil Persson. 21 | -------------------------------------------------------------------------------- /apps/example/src/assets/f.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wcandillon/react-native-webgpu/a6dbc83a14784a37a1d3b7ce57b839c70b479d2f/apps/example/src/assets/f.png -------------------------------------------------------------------------------- /apps/example/src/assets/moon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wcandillon/react-native-webgpu/a6dbc83a14784a37a1d3b7ce57b839c70b479d2f/apps/example/src/assets/moon.png -------------------------------------------------------------------------------- /apps/example/src/assets/react.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wcandillon/react-native-webgpu/a6dbc83a14784a37a1d3b7ce57b839c70b479d2f/apps/example/src/assets/react.png -------------------------------------------------------------------------------- /apps/example/src/assets/saturn.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wcandillon/react-native-webgpu/a6dbc83a14784a37a1d3b7ce57b839c70b479d2f/apps/example/src/assets/saturn.png -------------------------------------------------------------------------------- /apps/example/src/components/cube.ts: -------------------------------------------------------------------------------- 1 | export const cubeVertexSize = 4 * 10; // Byte size of one cube vertex. 2 | export const cubePositionOffset = 0; 3 | export const cubeColorOffset = 4 * 4; // Byte offset of cube vertex color attribute. 4 | export const cubeUVOffset = 4 * 8; 5 | export const cubeVertexCount = 36; 6 | 7 | // prettier-ignore 8 | export const cubeVertexArray = new Float32Array([ 9 | // float4 position, float4 color, float2 uv, 10 | 1, -1, 1, 1, 1, 0, 1, 1, 0, 1, 11 | -1, -1, 1, 1, 0, 0, 1, 1, 1, 1, 12 | -1, -1, -1, 1, 0, 0, 0, 1, 1, 0, 13 | 1, -1, -1, 1, 1, 0, 0, 1, 0, 0, 14 | 1, -1, 1, 1, 1, 0, 1, 1, 0, 1, 15 | -1, -1, -1, 1, 0, 0, 0, 1, 1, 0, 16 | 17 | 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 18 | 1, -1, 1, 1, 1, 0, 1, 1, 1, 1, 19 | 1, -1, -1, 1, 1, 0, 0, 1, 1, 0, 20 | 1, 1, -1, 1, 1, 1, 0, 1, 0, 0, 21 | 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 22 | 1, -1, -1, 1, 1, 0, 0, 1, 1, 0, 23 | 24 | -1, 1, 1, 1, 0, 1, 1, 1, 0, 1, 25 | 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 26 | 1, 1, -1, 1, 1, 1, 0, 1, 1, 0, 27 | -1, 1, -1, 1, 0, 1, 0, 1, 0, 0, 28 | -1, 1, 1, 1, 0, 1, 1, 1, 0, 1, 29 | 1, 1, -1, 1, 1, 1, 0, 1, 1, 0, 30 | 31 | -1, -1, 1, 1, 0, 0, 1, 1, 0, 1, 32 | -1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 33 | -1, 1, -1, 1, 0, 1, 0, 1, 1, 0, 34 | -1, -1, -1, 1, 0, 0, 0, 1, 0, 0, 35 | -1, -1, 1, 1, 0, 0, 1, 1, 0, 1, 36 | -1, 1, -1, 1, 0, 1, 0, 1, 1, 0, 37 | 38 | 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 39 | -1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 40 | -1, -1, 1, 1, 0, 0, 1, 1, 1, 0, 41 | -1, -1, 1, 1, 0, 0, 1, 1, 1, 0, 42 | 1, -1, 1, 1, 1, 0, 1, 1, 0, 0, 43 | 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 44 | 45 | 1, -1, -1, 1, 1, 0, 0, 1, 0, 1, 46 | -1, -1, -1, 1, 0, 0, 0, 1, 1, 1, 47 | -1, 1, -1, 1, 0, 1, 0, 1, 1, 0, 48 | 1, 1, -1, 1, 1, 1, 0, 1, 0, 0, 49 | 1, -1, -1, 1, 1, 0, 0, 1, 0, 1, 50 | -1, 1, -1, 1, 0, 1, 0, 1, 1, 0, 51 | ]); 52 | -------------------------------------------------------------------------------- /apps/example/src/components/meshes/stanfordDragon.ts: -------------------------------------------------------------------------------- 1 | import dragonRawData from './stanfordDragonData'; 2 | import { computeProjectedPlaneUVs, generateNormals } from './utils'; 3 | 4 | const { positions, normals, triangles } = generateNormals( 5 | Math.PI, 6 | dragonRawData.positions as [number, number, number][], 7 | dragonRawData.cells as [number, number, number][] 8 | ); 9 | 10 | const uvs = computeProjectedPlaneUVs(positions, 'xy'); 11 | 12 | // Push indices for an additional ground plane 13 | triangles.push( 14 | [positions.length, positions.length + 2, positions.length + 1], 15 | [positions.length, positions.length + 1, positions.length + 3] 16 | ); 17 | 18 | // Push vertex attributes for an additional ground plane 19 | // prettier-ignore 20 | positions.push( 21 | [-100, 20, -100], // 22 | [ 100, 20, 100], // 23 | [-100, 20, 100], // 24 | [ 100, 20, -100] 25 | ); 26 | normals.push( 27 | [0, 1, 0], // 28 | [0, 1, 0], // 29 | [0, 1, 0], // 30 | [0, 1, 0] 31 | ); 32 | uvs.push( 33 | [0, 0], // 34 | [1, 1], // 35 | [0, 1], // 36 | [1, 0] 37 | ); 38 | 39 | export const mesh = { 40 | positions, 41 | triangles, 42 | normals, 43 | uvs, 44 | }; 45 | -------------------------------------------------------------------------------- /apps/example/src/components/meshes/teapot.ts: -------------------------------------------------------------------------------- 1 | // @ts-expect-error 2 | import teapotData from "teapot"; 3 | 4 | import { computeSurfaceNormals } from "./utils"; 5 | 6 | export const mesh = { 7 | positions: teapotData.positions as [number, number, number][], 8 | triangles: teapotData.cells as [number, number, number][], 9 | normals: [] as [number, number, number][], 10 | }; 11 | 12 | // Compute surface normals 13 | mesh.normals = computeSurfaceNormals(mesh.positions, mesh.triangles); 14 | -------------------------------------------------------------------------------- /apps/example/src/components/useAssets.ts: -------------------------------------------------------------------------------- 1 | import { useEffect, useState } from "react"; 2 | import { Image } from "react-native"; 3 | import "react-native-wgpu"; 4 | 5 | export const fetchAsset = async (mod: number) => { 6 | const response = await fetch(Image.resolveAssetSource(mod).uri); 7 | return response; 8 | }; 9 | 10 | export const decodeImage = async (mod: number) => { 11 | const { uri } = Image.resolveAssetSource(mod); 12 | const response = await fetch(uri); 13 | const blob = await response.blob(); 14 | const image = await createImageBitmap(blob); 15 | return image; 16 | }; 17 | 18 | export interface AssetProps { 19 | assets: { 20 | di3D: ImageBitmap; 21 | saturn: ImageBitmap; 22 | moon: ImageBitmap; 23 | react: ImageBitmap; 24 | }; 25 | } 26 | 27 | const useImageData = (mod: number) => { 28 | const [imageData, setImageData] = useState(null); 29 | useEffect(() => { 30 | (async () => { 31 | setImageData(await decodeImage(mod)); 32 | })(); 33 | }, [mod]); 34 | return imageData; 35 | }; 36 | 37 | export const useAssets = () => { 38 | const di3D = useImageData(require("../assets/Di-3d.png")); 39 | const moon = useImageData(require("../assets/moon.png")); 40 | const saturn = useImageData(require("../assets/saturn.png")); 41 | const react = useImageData(require("../assets/react.png")); 42 | if (!di3D || !moon || !saturn || !react) { 43 | return null; 44 | } 45 | return { 46 | di3D, 47 | moon, 48 | saturn, 49 | react, 50 | }; 51 | }; 52 | -------------------------------------------------------------------------------- /apps/example/src/components/utils.ts: -------------------------------------------------------------------------------- 1 | export const toBeAssignedLater = () => undefined as unknown as GPUTextureView; 2 | -------------------------------------------------------------------------------- /apps/example/src/useClient.ts: -------------------------------------------------------------------------------- 1 | import { useEffect, useState } from "react"; 2 | import { Platform } from "react-native"; 3 | 4 | const ANDROID_WS_HOST = "10.0.2.2"; 5 | const IOS_WS_HOST = "localhost"; 6 | const HOST = Platform.OS === "android" ? ANDROID_WS_HOST : IOS_WS_HOST; 7 | const PORT = 4242; 8 | 9 | type UseClient = [client: WebSocket | null, hostname: string]; 10 | export const useClient = (): UseClient => { 11 | const [client, setClient] = useState(null); 12 | const [retry, setRetry] = useState(0); 13 | 14 | useEffect(() => { 15 | const url = `ws://${HOST}:${PORT}`; 16 | let it: ReturnType; 17 | const ws = new WebSocket(url); 18 | ws.onopen = () => { 19 | setClient(ws); 20 | ws.send(JSON.stringify({ OS: Platform.OS, arch: "paper" })); 21 | }; 22 | ws.onclose = () => { 23 | setClient(null); 24 | }; 25 | ws.onerror = () => { 26 | it = setTimeout(() => { 27 | ws.close(); 28 | // incrementing retry to rerun the effect 29 | setRetry((r) => r + 1); 30 | }, 500); 31 | }; 32 | return () => { 33 | ws.close(); 34 | clearTimeout(it); 35 | }; 36 | }, [retry]); 37 | return [client, HOST]; 38 | }; 39 | -------------------------------------------------------------------------------- /apps/example/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "eslint-config-react-native-wcandillon/tsconfig.base", 3 | "compilerOptions": { 4 | "noUncheckedIndexedAccess": false, 5 | "paths": { 6 | "react-native-wgpu": ["../../packages/webgpu/src/index"], 7 | "three": ["../../node_modules/@types/three/src/Three.WebGPU.d.ts"], 8 | "three/tsl": ["../../node_modules/@types/three/src/Three.TSL.d.ts"], 9 | "three/addons/*": ["../../node_modules/@types/three/examples/jsm/*"] 10 | }, 11 | "types": ["@webgpu/types", "@types/node"], 12 | }, 13 | "exclude": [ 14 | "**/Pods/**" 15 | ] 16 | } -------------------------------------------------------------------------------- /apps/example/visionos/Podfile: -------------------------------------------------------------------------------- 1 | ws_dir = Pathname.new(__dir__) 2 | ws_dir = ws_dir.parent until 3 | File.exist?("#{ws_dir}/node_modules/react-native-test-app/visionos/test_app.rb") || 4 | ws_dir.expand_path.to_s == '/' 5 | require "#{ws_dir}/node_modules/react-native-test-app/visionos/test_app.rb" 6 | 7 | workspace 'Example.xcworkspace' 8 | 9 | options = { 10 | :hermes_enabled => true 11 | } 12 | 13 | use_test_app! options 14 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "react-native-webgpu", 3 | "private": true, 4 | "workspaces": [ 5 | "packages/*", 6 | "apps/*" 7 | ], 8 | "resolutions": { 9 | "@types/react": "^18.2.44", 10 | "@webgpu/types": "^0.1.42", 11 | "@react-three/fiber@^8.17.6": "patch:@react-three/fiber@npm%3A8.17.6#./.yarn/patches/@react-three-fiber-npm-8.17.6-bc537e834c.patch" 12 | }, 13 | "packageManager": "yarn@3.6.1", 14 | "scripts": { 15 | "lint": "turbo run lint", 16 | "tsc": "turbo run tsc", 17 | "build:ios": "turbo run build:ios", 18 | "build:macos": "turbo run build:macos", 19 | "build:android": "turbo run build:android", 20 | "build": "turbo run build", 21 | "pod:install": "turbo run pod:install" 22 | }, 23 | "devDependencies": { 24 | "turbo": "^2.1.0" 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /packages/webgpu/.editorconfig: -------------------------------------------------------------------------------- 1 | # EditorConfig helps developers define and maintain consistent 2 | # coding styles between different editors and IDEs 3 | # editorconfig.org 4 | 5 | root = true 6 | 7 | [*] 8 | 9 | indent_style = space 10 | indent_size = 2 11 | 12 | end_of_line = lf 13 | charset = utf-8 14 | trim_trailing_whitespace = true 15 | insert_final_newline = true 16 | -------------------------------------------------------------------------------- /packages/webgpu/.eslintrc: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "react-native-wcandillon", 3 | "ignorePatterns": ["**/*/components/meshes"], 4 | "rules": { 5 | "no-bitwise": "off", 6 | "@typescript-eslint/no-require-imports": "off", 7 | "no-dupe-class-members": "off", 8 | "prettier/prettier": [ 9 | "error", 10 | { 11 | "trailingComma": "all" 12 | } 13 | ] 14 | } 15 | } -------------------------------------------------------------------------------- /packages/webgpu/.gitattributes: -------------------------------------------------------------------------------- 1 | *.pbxproj -text 2 | # specific for windows script files 3 | *.bat text eol=crlf -------------------------------------------------------------------------------- /packages/webgpu/.gitignore: -------------------------------------------------------------------------------- 1 | !scripts/build 2 | # OSX 3 | # 4 | .DS_Store 5 | 6 | # XDE 7 | .expo/ 8 | 9 | # VSCode 10 | .vscode/ 11 | jsconfig.json 12 | 13 | # Xcode 14 | # 15 | build/ 16 | *.pbxuser 17 | !default.pbxuser 18 | *.mode1v3 19 | !default.mode1v3 20 | *.mode2v3 21 | !default.mode2v3 22 | *.perspectivev3 23 | !default.perspectivev3 24 | xcuserdata 25 | *.xccheckout 26 | *.moved-aside 27 | DerivedData 28 | *.hmap 29 | *.ipa 30 | *.xcuserstate 31 | project.xcworkspace 32 | .xcode.env.local 33 | 34 | # Android/IJ 35 | # 36 | .classpath 37 | .cxx 38 | .gradle 39 | .idea 40 | .project 41 | .settings 42 | local.properties 43 | android.iml 44 | 45 | # node.js 46 | # 47 | node_modules/ 48 | npm-debug.log 49 | yarn-debug.log 50 | yarn-error.log 51 | 52 | # BUCK 53 | buck-out/ 54 | \.buckd/ 55 | android/app/libs 56 | android/keystores/debug.keystore 57 | 58 | # Yarn 59 | .yarn/* 60 | !.yarn/patches 61 | !.yarn/plugins 62 | !.yarn/releases 63 | !.yarn/sdks 64 | !.yarn/versions 65 | 66 | # Expo 67 | .expo/ 68 | 69 | # Turborepo 70 | .turbo/ 71 | 72 | # generated by bob 73 | lib/ 74 | -------------------------------------------------------------------------------- /packages/webgpu/.watchmanconfig: -------------------------------------------------------------------------------- 1 | {} -------------------------------------------------------------------------------- /packages/webgpu/LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2024 William Candillon 4 | Permission is hereby granted, free of charge, to any person obtaining a copy 5 | of this software and associated documentation files (the "Software"), to deal 6 | in the Software without restriction, including without limitation the rights 7 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 8 | copies of the Software, and to permit persons to whom the Software is 9 | furnished to do so, subject to the following conditions: 10 | 11 | The above copyright notice and this permission notice shall be included in all 12 | copies or substantial portions of the Software. 13 | 14 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 17 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 18 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 19 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 20 | SOFTWARE. 21 | -------------------------------------------------------------------------------- /packages/webgpu/android/cpp/platform/ThreadUtils.cpp: -------------------------------------------------------------------------------- 1 | // 2 | // ThreadUtils.cpp 3 | // react-native-nitro 4 | // 5 | // Created by Marc Rousavy on 14.07.24. 6 | // 7 | 8 | #include "ThreadUtils.h" 9 | #include 10 | #include 11 | #include 12 | #include 13 | #include 14 | 15 | namespace margelo { 16 | 17 | std::string ThreadUtils::getThreadName() { 18 | #ifdef HAVE_ANDROID_PTHREAD_SETNAME_NP 19 | // Try using pthread APIs 20 | pthread_t this_thread = pthread_self(); 21 | char thread_name[16]; // Thread name length limit in Android is 16 characters 22 | 23 | int result = 24 | pthread_getname_np(this_thread, thread_name, sizeof(thread_name)); 25 | if (result == 0) { 26 | return std::string(thread_name); 27 | } 28 | #endif 29 | 30 | // Fall back to this_thread ID 31 | std::stringstream stream; 32 | stream << std::this_thread::get_id(); 33 | std::string threadId = stream.str(); 34 | return "Thread #" + threadId; 35 | } 36 | 37 | void ThreadUtils::setThreadName(const std::string &name) { 38 | prctl(PR_SET_NAME, name.c_str(), 0, 0, 0); 39 | } 40 | 41 | } // namespace margelo 42 | -------------------------------------------------------------------------------- /packages/webgpu/android/gradle.properties: -------------------------------------------------------------------------------- 1 | Wgpu_kotlinVersion=1.7.0 2 | Wgpu_minSdkVersion=21 3 | Wgpu_targetSdkVersion=31 4 | Wgpu_compileSdkVersion=31 5 | Wgpu_ndkversion=21.4.7075529 6 | -------------------------------------------------------------------------------- /packages/webgpu/android/src/main/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 3 | 4 | -------------------------------------------------------------------------------- /packages/webgpu/android/src/main/java/com/webgpu/WebGPUAPI.java: -------------------------------------------------------------------------------- 1 | package com.webgpu; 2 | 3 | import android.view.Surface; 4 | 5 | import com.facebook.proguard.annotations.DoNotStrip; 6 | 7 | public interface WebGPUAPI { 8 | 9 | void surfaceCreated( 10 | Surface surface 11 | ); 12 | 13 | void surfaceChanged( 14 | Surface surface 15 | ); 16 | 17 | void surfaceDestroyed(); 18 | 19 | void surfaceOffscreen(); 20 | } 21 | -------------------------------------------------------------------------------- /packages/webgpu/android/src/main/java/com/webgpu/WebGPUBaseView.java: -------------------------------------------------------------------------------- 1 | package com.webgpu; 2 | 3 | import android.content.Context; 4 | import android.view.Surface; 5 | import android.view.View; 6 | import com.facebook.proguard.annotations.DoNotStrip; 7 | 8 | public abstract class WebGPUBaseView extends View { 9 | protected Integer mContextId; 10 | 11 | public WebGPUBaseView(Context context, Integer contextId) { 12 | super(context); 13 | mContextId = contextId; 14 | } 15 | 16 | protected void handleSurfaceCreate(Surface surface) { 17 | float density = getResources().getDisplayMetrics().density; 18 | float scaledWidth = getWidth() / density; 19 | float scaledHeight = getHeight() / density; 20 | onSurfaceCreate(surface, mContextId, scaledWidth, scaledHeight); 21 | } 22 | 23 | protected void handleSurfaceChanged(Surface surface) { 24 | float density = getResources().getDisplayMetrics().density; 25 | float scaledWidth = getWidth() / density; 26 | float scaledHeight = getHeight() / density; 27 | onSurfaceChanged(surface, mContextId, scaledWidth, scaledHeight); 28 | } 29 | 30 | protected void handleSurfaceDestroyed() { 31 | onSurfaceDestroy(mContextId); 32 | } 33 | 34 | @Override 35 | protected void onLayout(boolean changed, int left, int top, int right, int bottom) { 36 | super.onLayout(changed, left, top, right, bottom); 37 | } 38 | 39 | 40 | @DoNotStrip 41 | private native void onSurfaceCreate( 42 | Surface surface, 43 | int contextId, 44 | float width, 45 | float height 46 | ); 47 | 48 | @DoNotStrip 49 | private native void onSurfaceChanged( 50 | Surface surface, 51 | int contextId, 52 | float width, 53 | float height 54 | ); 55 | 56 | @DoNotStrip 57 | private native void onSurfaceDestroy(int contextId); 58 | 59 | @DoNotStrip 60 | protected native void switchToOffscreenSurface(int contextId); 61 | } 62 | -------------------------------------------------------------------------------- /packages/webgpu/android/src/main/java/com/webgpu/WebGPUModule.java: -------------------------------------------------------------------------------- 1 | package com.webgpu; 2 | 3 | import android.util.Log; 4 | 5 | import androidx.annotation.OptIn; 6 | 7 | import java.util.HashSet; 8 | import java.util.Set; 9 | 10 | import com.facebook.proguard.annotations.DoNotStrip; 11 | import com.facebook.react.bridge.ReactApplicationContext; 12 | import com.facebook.react.bridge.JavaScriptContextHolder; 13 | import com.facebook.react.bridge.ReactMethod; 14 | import com.facebook.react.common.annotations.FrameworkAPI; 15 | import com.facebook.react.module.annotations.ReactModule; 16 | import com.facebook.react.modules.blob.BlobModule; 17 | import com.facebook.react.modules.blob.BlobProvider; 18 | import com.facebook.react.turbomodule.core.CallInvokerHolderImpl; 19 | import com.facebook.react.turbomodule.core.interfaces.CallInvokerHolder; 20 | 21 | @ReactModule(name = WebGPUModule.NAME) 22 | public class WebGPUModule extends NativeWebGPUModuleSpec { 23 | static { 24 | System.loadLibrary("react-native-wgpu"); // Load the C++ library 25 | } 26 | 27 | public WebGPUModule(ReactApplicationContext reactContext) { 28 | super(reactContext); 29 | // Initialize the C++ module 30 | initialize(); 31 | } 32 | 33 | @OptIn(markerClass = FrameworkAPI.class) 34 | @ReactMethod(isBlockingSynchronousMethod = true) 35 | public boolean install() { 36 | ReactApplicationContext context = getReactApplicationContext(); 37 | JavaScriptContextHolder jsContext = context.getJavaScriptContextHolder(); 38 | CallInvokerHolder callInvokerHolder = context.getCatalystInstance().getJSCallInvokerHolder(); 39 | BlobModule blobModule = getReactApplicationContext().getNativeModule(BlobModule.class); 40 | if (blobModule == null) { 41 | throw new RuntimeException("React Native's BlobModule was not found!"); 42 | } 43 | initializeNative(jsContext.get(), (CallInvokerHolderImpl) callInvokerHolder, blobModule); 44 | return true; 45 | } 46 | 47 | @OptIn(markerClass = FrameworkAPI.class) 48 | @DoNotStrip 49 | private native void initializeNative(long jsRuntime, CallInvokerHolderImpl jsInvoker, BlobModule blobModule); 50 | } 51 | -------------------------------------------------------------------------------- /packages/webgpu/android/src/main/java/com/webgpu/WebGPUSurfaceView.java: -------------------------------------------------------------------------------- 1 | package com.webgpu; 2 | 3 | import android.annotation.SuppressLint; 4 | import android.content.Context; 5 | import android.view.SurfaceHolder; 6 | import android.view.SurfaceView; 7 | 8 | import androidx.annotation.NonNull; 9 | 10 | @SuppressLint("ViewConstructor") 11 | public class WebGPUSurfaceView extends SurfaceView implements SurfaceHolder.Callback { 12 | 13 | WebGPUAPI mApi; 14 | 15 | public WebGPUSurfaceView(Context context, WebGPUAPI api) { 16 | super(context); 17 | mApi = api; 18 | getHolder().addCallback(this); 19 | } 20 | 21 | @Override 22 | protected void onDetachedFromWindow() { 23 | super.onDetachedFromWindow(); 24 | mApi.surfaceDestroyed(); 25 | } 26 | 27 | @Override 28 | public void surfaceCreated(@NonNull SurfaceHolder holder) { 29 | mApi.surfaceCreated(holder.getSurface()); 30 | } 31 | 32 | @Override 33 | public void surfaceChanged(@NonNull SurfaceHolder holder, int format, int width, int height) { 34 | mApi.surfaceChanged(holder.getSurface()); 35 | } 36 | 37 | @Override 38 | public void surfaceDestroyed(@NonNull SurfaceHolder holder) { 39 | mApi.surfaceOffscreen(); 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /packages/webgpu/android/src/main/java/com/webgpu/WebGPUTextureView.java: -------------------------------------------------------------------------------- 1 | package com.webgpu; 2 | 3 | import android.annotation.SuppressLint; 4 | import android.content.Context; 5 | import android.graphics.SurfaceTexture; 6 | import android.view.Surface; 7 | import android.view.TextureView; 8 | import androidx.annotation.NonNull; 9 | 10 | import org.w3c.dom.Text; 11 | 12 | @SuppressLint("ViewConstructor") 13 | public class WebGPUTextureView extends TextureView implements TextureView.SurfaceTextureListener { 14 | 15 | WebGPUAPI mApi; 16 | 17 | public WebGPUTextureView(Context context, WebGPUAPI api) { 18 | super(context); 19 | mApi = api; 20 | setOpaque(false); 21 | setSurfaceTextureListener(this); 22 | } 23 | 24 | @Override 25 | public void onSurfaceTextureAvailable(@NonNull SurfaceTexture surfaceTexture, int width, int height) { 26 | Surface surface = new Surface(surfaceTexture); 27 | mApi.surfaceCreated(surface); 28 | } 29 | 30 | @Override 31 | public void onSurfaceTextureSizeChanged(@NonNull SurfaceTexture surfaceTexture, int width, int height) { 32 | Surface surface = new Surface(surfaceTexture); 33 | mApi.surfaceChanged(surface); 34 | } 35 | 36 | @Override 37 | public boolean onSurfaceTextureDestroyed(@NonNull SurfaceTexture surfaceTexture) { 38 | mApi.surfaceDestroyed(); 39 | return true; 40 | } 41 | 42 | @Override 43 | public void onSurfaceTextureUpdated(@NonNull SurfaceTexture surfaceTexture) { 44 | // No implementation needed 45 | } 46 | } 47 | -------------------------------------------------------------------------------- /packages/webgpu/android/src/main/java/com/webgpu/WebGPUViewManager.java: -------------------------------------------------------------------------------- 1 | package com.webgpu; 2 | 3 | import androidx.annotation.NonNull; 4 | import androidx.annotation.Nullable; 5 | 6 | import com.facebook.react.module.annotations.ReactModule; 7 | import com.facebook.react.uimanager.ThemedReactContext; 8 | import com.facebook.react.uimanager.annotations.ReactProp; 9 | 10 | @ReactModule(name = WebGPUViewManager.NAME) 11 | public class WebGPUViewManager extends WebGPUViewManagerSpec { 12 | 13 | public static final String NAME = "WebGPUView"; 14 | 15 | @NonNull 16 | @Override 17 | public String getName() { 18 | return NAME; 19 | } 20 | 21 | @NonNull 22 | @Override 23 | public WebGPUView createViewInstance(@NonNull ThemedReactContext context) { 24 | return new WebGPUView(context); 25 | } 26 | 27 | @Override 28 | @ReactProp(name = "transparent") 29 | public void setTransparent(WebGPUView view, boolean value) { 30 | view.setTransparent(value); 31 | } 32 | 33 | @Override 34 | @ReactProp(name = "contextId") 35 | public void setContextId(WebGPUView view, int value) { 36 | view.setContextId(value); 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /packages/webgpu/android/src/main/java/com/webgpu/WebGPUViewPackage.java: -------------------------------------------------------------------------------- 1 | 2 | package com.webgpu; 3 | 4 | import com.facebook.react.ReactPackage; 5 | import com.facebook.react.bridge.NativeModule; 6 | import com.facebook.react.bridge.ReactApplicationContext; 7 | import com.facebook.react.uimanager.ViewManager; 8 | 9 | import java.util.ArrayList; 10 | import java.util.Arrays; 11 | import java.util.List; 12 | 13 | public class WebGPUViewPackage implements ReactPackage { 14 | @Override 15 | public List createViewManagers(ReactApplicationContext reactContext) { 16 | List viewManagers = new ArrayList<>(); 17 | viewManagers.add(new WebGPUViewManager()); 18 | return viewManagers; 19 | } 20 | 21 | 22 | @Override 23 | public List createNativeModules(ReactApplicationContext reactContext) { 24 | return List.of(new WebGPUModule(reactContext)); 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /packages/webgpu/android/src/newarch/com/webgpu/WebGPUViewManagerSpec.java: -------------------------------------------------------------------------------- 1 | package com.webgpu; 2 | 3 | import android.view.View; 4 | 5 | import androidx.annotation.Nullable; 6 | 7 | import com.facebook.react.uimanager.SimpleViewManager; 8 | import com.facebook.react.uimanager.ViewManagerDelegate; 9 | import com.facebook.react.viewmanagers.WebGPUViewManagerDelegate; 10 | import com.facebook.react.viewmanagers.WebGPUViewManagerInterface; 11 | 12 | public abstract class WebGPUViewManagerSpec extends SimpleViewManager implements WebGPUViewManagerInterface { 13 | private final ViewManagerDelegate mDelegate; 14 | 15 | public WebGPUViewManagerSpec() { 16 | mDelegate = new WebGPUViewManagerDelegate(this); 17 | } 18 | 19 | @Nullable 20 | @Override 21 | protected ViewManagerDelegate getDelegate() { 22 | return mDelegate; 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /packages/webgpu/android/src/oldarch/com/webgpu/NativeWebGPUModuleSpec.java: -------------------------------------------------------------------------------- 1 | package com.webgpu; 2 | 3 | import androidx.annotation.NonNull; 4 | import androidx.annotation.Nullable; 5 | 6 | import com.facebook.react.bridge.ReactApplicationContext; 7 | import com.facebook.react.bridge.ReactContextBaseJavaModule; 8 | 9 | class NativeWebGPUModuleSpec extends ReactContextBaseJavaModule { 10 | 11 | public static final String NAME = "WebGPUModule"; 12 | 13 | public NativeWebGPUModuleSpec(@Nullable ReactApplicationContext reactContext) { 14 | super(reactContext); 15 | } 16 | 17 | @NonNull 18 | @Override 19 | public String getName() { 20 | return NAME; 21 | } 22 | 23 | } 24 | -------------------------------------------------------------------------------- /packages/webgpu/android/src/oldarch/com/webgpu/WebGPUViewManagerSpec.java: -------------------------------------------------------------------------------- 1 | package com.webgpu; 2 | 3 | import android.view.View; 4 | 5 | import androidx.annotation.Nullable; 6 | 7 | import com.facebook.react.uimanager.SimpleViewManager; 8 | 9 | public abstract class WebGPUViewManagerSpec extends SimpleViewManager { 10 | public abstract void setContextId(T view, int contextId); 11 | public abstract void setTransparent(T view, boolean transparency); 12 | } 13 | -------------------------------------------------------------------------------- /packages/webgpu/apple/ApplePlatformContext.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "PlatformContext.h" 4 | 5 | namespace rnwgpu { 6 | 7 | class ApplePlatformContext : public PlatformContext { 8 | public: 9 | ApplePlatformContext(); 10 | ~ApplePlatformContext() = default; 11 | 12 | wgpu::Surface makeSurface(wgpu::Instance instance, void *surface, int width, 13 | int height) override; 14 | 15 | ImageData createImageBitmap(std::string blobId, double offset, 16 | double size) override; 17 | }; 18 | 19 | } // namespace rnwgpu 20 | -------------------------------------------------------------------------------- /packages/webgpu/apple/MetalView.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #import "RNWGUIKit.h" 4 | #import "WebGPUModule.h" 5 | 6 | @interface MetalView : RNWGPlatformView 7 | 8 | @property NSNumber *contextId; 9 | 10 | - (void)configure; 11 | - (void)update; 12 | 13 | @end 14 | -------------------------------------------------------------------------------- /packages/webgpu/apple/MetalView.mm: -------------------------------------------------------------------------------- 1 | #import "MetalView.h" 2 | #import "webgpu_cpp.h" 3 | 4 | #ifndef RCT_NEW_ARCH_ENABLED 5 | #import 6 | #endif // RCT_NEW_ARCH_ENABLED 7 | 8 | @implementation MetalView { 9 | BOOL _isConfigured; 10 | } 11 | 12 | #if !TARGET_OS_OSX 13 | + (Class)layerClass { 14 | return [CAMetalLayer class]; 15 | } 16 | #else // !TARGET_OS_OSX 17 | - (instancetype)init { 18 | self = [super init]; 19 | if (self) { 20 | self.wantsLayer = true; 21 | self.layer = [CAMetalLayer layer]; 22 | } 23 | return self; 24 | } 25 | #endif // !TARGET_OS_OSX 26 | 27 | - (void)configure { 28 | auto size = self.frame.size; 29 | std::shared_ptr manager = [WebGPUModule getManager]; 30 | void *nativeSurface = (__bridge void *)self.layer; 31 | auto ®istry = rnwgpu::SurfaceRegistry::getInstance(); 32 | auto gpu = manager->_gpu; 33 | auto surface = manager->_platformContext->makeSurface( 34 | gpu, nativeSurface, size.width, size.height); 35 | registry 36 | .getSurfaceInfoOrCreate([_contextId intValue], gpu, size.width, 37 | size.height) 38 | ->switchToOnscreen(nativeSurface, surface); 39 | } 40 | 41 | - (void)update { 42 | auto size = self.frame.size; 43 | auto ®istry = rnwgpu::SurfaceRegistry::getInstance(); 44 | registry.getSurfaceInfo([_contextId intValue]) 45 | ->resize(size.width, size.height); 46 | } 47 | 48 | - (void)dealloc { 49 | auto ®istry = rnwgpu::SurfaceRegistry::getInstance(); 50 | // Remove the surface info from the registry 51 | registry.removeSurfaceInfo([_contextId intValue]); 52 | } 53 | 54 | #ifndef RCT_NEW_ARCH_ENABLED 55 | // Paper only method 56 | // TODO: this method is wrong, it appears to call configureSurface instead of 57 | // updateSurface sometimes 58 | - (void)reactSetFrame:(CGRect)frame { 59 | [super reactSetFrame:frame]; 60 | if (!_isConfigured) { 61 | [self configure]; 62 | _isConfigured = YES; 63 | } else { 64 | [self update]; 65 | } 66 | } 67 | #endif // RCT_NEW_ARCH_ENABLED 68 | 69 | @end 70 | -------------------------------------------------------------------------------- /packages/webgpu/apple/RNWGUIKit.h: -------------------------------------------------------------------------------- 1 | #if !TARGET_OS_OSX 2 | #import 3 | #else 4 | #import 5 | #endif 6 | 7 | #if !TARGET_OS_OSX 8 | typedef UIView RNWGPlatformView; 9 | #else 10 | typedef NSView RNWGPlatformView; 11 | #endif 12 | -------------------------------------------------------------------------------- /packages/webgpu/apple/WebGPUModule.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #import "RNWebGPUManager.h" 4 | #import 5 | #import 6 | 7 | #ifdef RCT_NEW_ARCH_ENABLED 8 | #import 9 | @interface WebGPUModule : RCTEventEmitter 10 | #else 11 | @interface WebGPUModule : RCTEventEmitter 12 | #endif 13 | 14 | @property(nonatomic, weak) RCTBridge *bridge; 15 | @property(nonatomic, weak) RCTModuleRegistry *moduleRegistry; 16 | 17 | + (std::shared_ptr)getManager; 18 | 19 | @end 20 | -------------------------------------------------------------------------------- /packages/webgpu/apple/WebGPUView.h: -------------------------------------------------------------------------------- 1 | #ifdef RCT_NEW_ARCH_ENABLED 2 | #pragma once 3 | 4 | #import "MetalView.h" 5 | #import 6 | #import 7 | 8 | NS_ASSUME_NONNULL_BEGIN 9 | 10 | @interface WebGPUView : RCTViewComponentView 11 | @end 12 | 13 | NS_ASSUME_NONNULL_END 14 | 15 | #endif /* RCT_NEW_ARCH_ENABLED */ 16 | -------------------------------------------------------------------------------- /packages/webgpu/apple/WebGPUViewManager.mm: -------------------------------------------------------------------------------- 1 | #import "MetalView.h" 2 | #import "RCTBridge.h" 3 | #import "RNWGUIKit.h" 4 | #import "WebGPUModule.h" 5 | #import 6 | #import 7 | 8 | @interface WebGPUViewManager : RCTViewManager 9 | @end 10 | 11 | @implementation WebGPUViewManager 12 | 13 | RCT_EXPORT_MODULE(WebGPUView) 14 | 15 | - (RNWGPlatformView *)view { 16 | return [MetalView new]; 17 | } 18 | 19 | RCT_CUSTOM_VIEW_PROPERTY(contextId, NSNumber, RNWGPlatformView) { 20 | NSNumber *contextId = [RCTConvert NSNumber:json]; 21 | [(MetalView *)view setContextId:contextId]; 22 | } 23 | 24 | @end 25 | -------------------------------------------------------------------------------- /packages/webgpu/apple/platform/ThreadUtils.cpp: -------------------------------------------------------------------------------- 1 | // 2 | // ThreadUtils.cpp 3 | // react-native-nitro 4 | // 5 | // Created by Marc Rousavy on 14.07.24. 6 | // 7 | 8 | #include "ThreadUtils.h" 9 | #include 10 | #include 11 | #include 12 | 13 | namespace margelo { 14 | 15 | std::string ThreadUtils::getThreadName() { 16 | // Try using pthread APIs 17 | char name[256]; 18 | if (pthread_getname_np(pthread_self(), name, sizeof(name)) == 0) { 19 | return std::string(name); 20 | } 21 | 22 | // Fall back to this_thread ID 23 | std::stringstream stream; 24 | stream << std::this_thread::get_id(); 25 | std::string threadId = stream.str(); 26 | return "Thread #" + threadId; 27 | } 28 | 29 | void ThreadUtils::setThreadName(const std::string &name) { 30 | pthread_setname_np(name.c_str()); 31 | } 32 | 33 | } // namespace margelo 34 | -------------------------------------------------------------------------------- /packages/webgpu/babel.config.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | presets: ['module:@react-native/babel-preset'], 3 | }; 4 | -------------------------------------------------------------------------------- /packages/webgpu/cpp/jsi/RNFPromise.cpp: -------------------------------------------------------------------------------- 1 | // 2 | // Created by Marc Rousavy on 22.02.24. 3 | // 4 | #include "RNFPromise.h" 5 | #include 6 | #include 7 | #include 8 | #include 9 | 10 | namespace margelo { 11 | 12 | namespace jsi = facebook::jsi; 13 | 14 | Promise::Promise(jsi::Runtime& runtime, jsi::Function&& resolver, jsi::Function&& rejecter) 15 | : runtime(runtime), _resolver(std::move(resolver)), _rejecter(std::move(rejecter)) {} 16 | 17 | jsi::Value Promise::createPromise(jsi::Runtime& runtime, RunPromise run) { 18 | // Get Promise ctor from global 19 | auto promiseCtor = runtime.global().getPropertyAsFunction(runtime, "Promise"); 20 | 21 | auto promiseCallback = jsi::Function::createFromHostFunction( 22 | runtime, jsi::PropNameID::forUtf8(runtime, "PromiseCallback"), 2, 23 | [=](jsi::Runtime& runtime, const jsi::Value& thisValue, const jsi::Value* arguments, size_t count) -> jsi::Value { 24 | // Call function 25 | auto resolver = arguments[0].asObject(runtime).asFunction(runtime); 26 | auto rejecter = arguments[1].asObject(runtime).asFunction(runtime); 27 | auto promise = std::make_shared(runtime, std::move(resolver), std::move(rejecter)); 28 | run(runtime, promise); 29 | 30 | return jsi::Value::undefined(); 31 | }); 32 | 33 | return promiseCtor.callAsConstructor(runtime, promiseCallback); 34 | } 35 | 36 | void Promise::resolve(jsi::Value&& result) { 37 | _resolver.call(runtime, std::move(result)); 38 | } 39 | 40 | void Promise::reject(std::string message) { 41 | jsi::JSError error(runtime, message); 42 | _rejecter.call(runtime, error.value()); 43 | } 44 | 45 | } // namespace margelo 46 | -------------------------------------------------------------------------------- /packages/webgpu/cpp/jsi/RNFPromise.h: -------------------------------------------------------------------------------- 1 | // 2 | // Created by Marc Rousavy on 22.02.24. 3 | // 4 | #pragma once 5 | 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include 11 | 12 | namespace margelo { 13 | 14 | namespace jsi = facebook::jsi; 15 | 16 | class Promise { 17 | public: 18 | Promise(jsi::Runtime& runtime, jsi::Function&& resolver, jsi::Function&& rejecter); 19 | 20 | void resolve(jsi::Value&& result); 21 | void reject(std::string error); 22 | 23 | public: 24 | jsi::Runtime& runtime; 25 | 26 | private: 27 | jsi::Function _resolver; 28 | jsi::Function _rejecter; 29 | 30 | public: 31 | using RunPromise = std::function promise)>; 32 | /** 33 | Create a new Promise and runs the given `run` function. 34 | */ 35 | static jsi::Value createPromise(jsi::Runtime& runtime, RunPromise run); 36 | }; 37 | 38 | } // namespace margelo 39 | -------------------------------------------------------------------------------- /packages/webgpu/cpp/jsi/RNFRuntimeCache.cpp: -------------------------------------------------------------------------------- 1 | // 2 | // Created by Marc Rousavy on 22.02.24. 3 | // 4 | #include 5 | 6 | #include 7 | #include 8 | #include 9 | #include 10 | 11 | #include "RNFRuntimeCache.h" 12 | 13 | namespace margelo { 14 | 15 | static std::unordered_map> listeners; 16 | 17 | struct RuntimeLifecycleMonitorObject : public jsi::HostObject { 18 | jsi::Runtime* _rt; 19 | explicit RuntimeLifecycleMonitorObject(jsi::Runtime* rt) : _rt(rt) {} 20 | ~RuntimeLifecycleMonitorObject() { 21 | auto listenersSet = listeners.find(_rt); 22 | if (listenersSet != listeners.end()) { 23 | for (auto listener : listenersSet->second) { 24 | listener->onRuntimeDestroyed(_rt); 25 | } 26 | listeners.erase(listenersSet); 27 | } 28 | } 29 | }; 30 | 31 | void RuntimeLifecycleMonitor::addListener(jsi::Runtime& rt, RuntimeLifecycleListener* listener) { 32 | auto listenersSet = listeners.find(&rt); 33 | if (listenersSet == listeners.end()) { 34 | // We install a global host object in the provided runtime, this way we can 35 | // use that host object destructor to get notified when the runtime is being 36 | // terminated. We use a unique name for the object as it gets saved with the 37 | // runtime's global object. 38 | rt.global().setProperty(rt, "__rnfl_rt_lifecycle_monitor", 39 | jsi::Object::createFromHostObject(rt, std::make_shared(&rt))); 40 | std::unordered_set newSet; 41 | newSet.insert(listener); 42 | listeners.emplace(&rt, std::move(newSet)); 43 | } else { 44 | listenersSet->second.insert(listener); 45 | } 46 | } 47 | 48 | void RuntimeLifecycleMonitor::removeListener(jsi::Runtime& rt, RuntimeLifecycleListener* listener) { 49 | auto listenersSet = listeners.find(&rt); 50 | if (listenersSet == listeners.end()) { 51 | // nothing to do here 52 | } else { 53 | listenersSet->second.erase(listener); 54 | } 55 | } 56 | 57 | } // namespace margelo 58 | -------------------------------------------------------------------------------- /packages/webgpu/cpp/jsi/RNFWorkletRuntimeCollector.h: -------------------------------------------------------------------------------- 1 | // 2 | // Created by Marc Rousavy on 22.02.24. 3 | // 4 | #pragma once 5 | 6 | #include "RNFWorkletRuntimeRegistry.h" 7 | 8 | #include 9 | 10 | #include 11 | 12 | namespace margelo { 13 | 14 | // From: 15 | // https://github.com/software-mansion/react-native-reanimated/blob/6cb1a66f1a68cac8079de2b6b305d22359847e51/Common/cpp/ReanimatedRuntime/WorkletRuntimeCollector.h 16 | class WorkletRuntimeCollector : public jsi::HostObject { 17 | // When worklet runtime is created, we inject an instance of this class as a 18 | // `jsi::HostObject` into the global object. When worklet runtime is 19 | // terminated, the object is garbage-collected, which runs the C++ destructor. 20 | // In the destructor, we unregister the worklet runtime from the registry. 21 | 22 | public: 23 | explicit WorkletRuntimeCollector(jsi::Runtime& runtime) : _runtime(runtime) { 24 | Logger::log("WorkletRuntimeCollector", "Registering WorkletRuntime %p", &runtime); 25 | RNFWorkletRuntimeRegistry::registerRuntime(_runtime); 26 | } 27 | 28 | ~WorkletRuntimeCollector() { 29 | Logger::log("WorkletRuntimeCollector", "Unregistering WorkletRuntime %p", &_runtime); 30 | RNFWorkletRuntimeRegistry::unregisterRuntime(_runtime); 31 | } 32 | 33 | static void install(jsi::Runtime& rt) { 34 | auto collector = std::make_shared(rt); 35 | auto object = jsi::Object::createFromHostObject(rt, collector); 36 | rt.global().setProperty(rt, "__workletRuntimeCollector", object); 37 | } 38 | 39 | private: 40 | jsi::Runtime& _runtime; 41 | }; 42 | 43 | } // namespace margelo 44 | -------------------------------------------------------------------------------- /packages/webgpu/cpp/jsi/RNFWorkletRuntimeRegistry.cpp: -------------------------------------------------------------------------------- 1 | // 2 | // Created by Marc Rousavy on 22.02.24. 3 | // 4 | #include "RNFWorkletRuntimeRegistry.h" 5 | 6 | namespace margelo { 7 | 8 | std::set RNFWorkletRuntimeRegistry::registry_{}; 9 | std::mutex RNFWorkletRuntimeRegistry::mutex_{}; 10 | 11 | } // namespace margelo 12 | -------------------------------------------------------------------------------- /packages/webgpu/cpp/jsi/RNFWorkletRuntimeRegistry.h: -------------------------------------------------------------------------------- 1 | // 2 | // Created by Marc Rousavy on 22.02.24. 3 | // 4 | #pragma once 5 | 6 | #include 7 | 8 | #include 9 | #include 10 | 11 | namespace jsi = facebook::jsi; 12 | 13 | namespace margelo { 14 | 15 | // From: 16 | // https://github.com/software-mansion/react-native-reanimated/blob/6cb1a66f1a68cac8079de2b6b305d22359847e51/Common/cpp/ReanimatedRuntime/WorkletRuntimeRegistry.h 17 | class RNFWorkletRuntimeRegistry { 18 | private: 19 | static std::set registry_; 20 | static std::mutex mutex_; // Protects `registry_`. 21 | 22 | RNFWorkletRuntimeRegistry() {} // private ctor 23 | 24 | static void registerRuntime(jsi::Runtime& runtime) { 25 | std::lock_guard lock(mutex_); 26 | registry_.insert(&runtime); 27 | } 28 | 29 | static void unregisterRuntime(jsi::Runtime& runtime) { 30 | std::lock_guard lock(mutex_); 31 | registry_.erase(&runtime); 32 | } 33 | 34 | friend class WorkletRuntimeCollector; 35 | 36 | public: 37 | static bool isRuntimeAlive(jsi::Runtime* runtime) { 38 | assert(runtime != nullptr); 39 | std::lock_guard lock(mutex_); 40 | return registry_.find(runtime) != registry_.end(); 41 | } 42 | }; 43 | 44 | } // namespace margelo 45 | -------------------------------------------------------------------------------- /packages/webgpu/cpp/platform/ThreadUtils.h: -------------------------------------------------------------------------------- 1 | // 2 | // ThreadUtils.hpp 3 | // react-native-nitro 4 | // 5 | // Created by Marc Rousavy on 14.07.24. 6 | // 7 | #pragma once 8 | 9 | #include 10 | 11 | namespace margelo { 12 | 13 | class ThreadUtils final { 14 | public: 15 | ThreadUtils() = delete; 16 | 17 | /** 18 | * Get the current Thread's name. 19 | * This is implemented differently on iOS and Android. 20 | */ 21 | static std::string getThreadName(); 22 | 23 | /** 24 | * Set the current Thread's name. 25 | * This is implemented differently on iOS and Android. 26 | */ 27 | static void setThreadName(const std::string &name); 28 | }; 29 | 30 | } // namespace margelo 31 | -------------------------------------------------------------------------------- /packages/webgpu/cpp/rnwgpu/PlatformContext.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | #include 5 | #include 6 | 7 | #include "webgpu/webgpu_cpp.h" 8 | 9 | namespace rnwgpu { 10 | 11 | struct ImageData { 12 | std::vector data; 13 | size_t width; 14 | size_t height; 15 | wgpu::TextureFormat format; 16 | }; 17 | 18 | class PlatformContext { 19 | public: 20 | PlatformContext() = default; 21 | virtual ~PlatformContext() = default; 22 | 23 | virtual wgpu::Surface makeSurface(wgpu::Instance instance, void *surface, 24 | int width, int height) = 0; 25 | virtual ImageData createImageBitmap(std::string blobId, double offset, 26 | double size) = 0; 27 | }; 28 | 29 | } // namespace rnwgpu 30 | -------------------------------------------------------------------------------- /packages/webgpu/cpp/rnwgpu/RNWebGPUManager.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | 5 | #include "GPU.h" 6 | #include "PlatformContext.h" 7 | #include "SurfaceRegistry.h" 8 | 9 | namespace facebook { 10 | namespace jsi { 11 | class Runtime; 12 | } // namespace jsi 13 | namespace react { 14 | class CallInvoker; 15 | } 16 | } // namespace facebook 17 | 18 | namespace rnwgpu { 19 | 20 | namespace jsi = facebook::jsi; 21 | namespace react = facebook::react; 22 | 23 | class RNWebGPUManager { 24 | public: 25 | RNWebGPUManager(jsi::Runtime *jsRuntime, 26 | std::shared_ptr jsCallInvoker, 27 | std::shared_ptr platformContext); 28 | ~RNWebGPUManager(); 29 | 30 | private: 31 | jsi::Runtime *_jsRuntime; 32 | std::shared_ptr _jsCallInvoker; 33 | 34 | public: 35 | wgpu::Instance _gpu; 36 | std::shared_ptr _platformContext; 37 | }; 38 | 39 | } // namespace rnwgpu 40 | -------------------------------------------------------------------------------- /packages/webgpu/cpp/rnwgpu/api/AsyncRunner.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "webgpu/webgpu_cpp.h" 4 | 5 | #include 6 | #include 7 | 8 | namespace rnwgpu { 9 | 10 | class AsyncRunner { 11 | public: 12 | explicit AsyncRunner(wgpu::Instance *instance) : instance(instance) {} 13 | 14 | template auto runAsync(F &&func) { 15 | return std::async( 16 | std::launch::async, [this, func = std::forward(func)]() { 17 | if constexpr (std::is_invocable_v) { 18 | return func(instance); 19 | } else { 20 | auto future = func(); 21 | instance->WaitAny(future, UINT64_MAX); 22 | } 23 | }); 24 | } 25 | 26 | private: 27 | wgpu::Instance *instance; 28 | }; 29 | 30 | } // namespace rnwgpu 31 | -------------------------------------------------------------------------------- /packages/webgpu/cpp/rnwgpu/api/Canvas.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | #include 5 | 6 | #include "Unions.h" 7 | 8 | #include "webgpu/webgpu_cpp.h" 9 | 10 | #include "RNFHybridObject.h" 11 | 12 | namespace rnwgpu { 13 | 14 | namespace m = margelo; 15 | 16 | class Canvas : public m::HybridObject { 17 | public: 18 | explicit Canvas(void *surface, const int width, const int height) 19 | : HybridObject("Canvas"), _surface(surface), _width(width), 20 | _height(height), _clientWidth(width), _clientHeight(height) {} 21 | 22 | int getWidth() { return _width; } 23 | int getHeight() { return _height; } 24 | 25 | void setWidth(const int width) { _width = width; } 26 | void setHeight(const int height) { _height = height; } 27 | 28 | int getClientWidth() { return _clientWidth; } 29 | int getClientHeight() { return _clientHeight; } 30 | 31 | void setClientWidth(const int width) { _clientWidth = width; } 32 | 33 | void setClientHeight(const int height) { _clientHeight = height; } 34 | 35 | void *getSurface() { return _surface; } 36 | 37 | void loadHybridMethods() override { 38 | registerHybridGetter("surface", &Canvas::getSurface, this); 39 | registerHybridGetter("width", &Canvas::getWidth, this); 40 | registerHybridGetter("height", &Canvas::getHeight, this); 41 | registerHybridGetter("clientWidth", &Canvas::getClientWidth, this); 42 | registerHybridGetter("clientHeight", &Canvas::getClientHeight, this); 43 | registerHybridSetter("width", &Canvas::setWidth, this); 44 | registerHybridSetter("height", &Canvas::setHeight, this); 45 | } 46 | 47 | private: 48 | void *_surface; 49 | int _width; 50 | int _height; 51 | int _clientWidth; 52 | int _clientHeight; 53 | }; 54 | 55 | } // namespace rnwgpu 56 | -------------------------------------------------------------------------------- /packages/webgpu/cpp/rnwgpu/api/External.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "webgpu/webgpu_cpp.h" 4 | 5 | namespace rnwgpu { 6 | enum class PredefinedColorSpace : uint32_t { 7 | DisplayP3 = 0, 8 | Srgb = 1, 9 | }; 10 | 11 | enum class PremultiplyAlpha : uint32_t { Default = 0, None = 1, Premultiply }; 12 | } // namespace rnwgpu 13 | -------------------------------------------------------------------------------- /packages/webgpu/cpp/rnwgpu/api/GPU.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | 9 | #include "Unions.h" 10 | 11 | #include "RNFHybridObject.h" 12 | 13 | #include "AsyncRunner.h" 14 | 15 | #include "dawn/dawn_proc.h" 16 | #include "dawn/native/DawnNative.h" 17 | #include "webgpu/webgpu_cpp.h" 18 | 19 | #include "GPUAdapter.h" 20 | #include "GPURequestAdapterOptions.h" 21 | 22 | #include 23 | 24 | namespace rnwgpu { 25 | 26 | namespace m = margelo; 27 | 28 | class GPU : public m::HybridObject { 29 | public: 30 | GPU() : HybridObject("GPU") { 31 | wgpu::InstanceDescriptor instanceDesc; 32 | instanceDesc.capabilities.timedWaitAnyEnable = true; 33 | instanceDesc.capabilities.timedWaitAnyMaxCount = 64; 34 | _instance = wgpu::CreateInstance(&instanceDesc); 35 | auto instance = &_instance; 36 | _async = std::make_shared(instance); 37 | } 38 | 39 | public: 40 | std::string getBrand() { return _name; } 41 | 42 | std::future>> 43 | requestAdapter( 44 | std::optional> options); 45 | wgpu::TextureFormat getPreferredCanvasFormat(); 46 | 47 | std::unordered_set getWgslLanguageFeatures(); 48 | 49 | void loadHybridMethods() override { 50 | registerHybridGetter("__brand", &GPU::getBrand, this); 51 | registerHybridMethod("requestAdapter", &GPU::requestAdapter, this); 52 | registerHybridMethod("getPreferredCanvasFormat", 53 | &GPU::getPreferredCanvasFormat, this); 54 | registerHybridGetter("wgslLanguageFeatures", &GPU::getWgslLanguageFeatures, 55 | this); 56 | } 57 | 58 | inline const wgpu::Instance get() { return _instance; } 59 | 60 | private: 61 | wgpu::Instance _instance; 62 | std::shared_ptr _async; 63 | }; 64 | 65 | } // namespace rnwgpu 66 | -------------------------------------------------------------------------------- /packages/webgpu/cpp/rnwgpu/api/GPUAdapter.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | #include 5 | #include 6 | #include 7 | 8 | #include "Unions.h" 9 | 10 | #include "RNFHybridObject.h" 11 | 12 | #include "AsyncRunner.h" 13 | 14 | #include "webgpu/webgpu_cpp.h" 15 | 16 | #include "GPUAdapterInfo.h" 17 | #include "GPUDevice.h" 18 | #include "GPUDeviceDescriptor.h" 19 | #include "GPUSupportedLimits.h" 20 | 21 | namespace rnwgpu { 22 | 23 | namespace m = margelo; 24 | 25 | class GPUAdapter : public m::HybridObject { 26 | public: 27 | explicit GPUAdapter(wgpu::Adapter instance, 28 | std::shared_ptr async) 29 | : HybridObject("GPUAdapter"), _instance(instance), _async(async) {} 30 | 31 | public: 32 | std::string getBrand() { return _name; } 33 | 34 | std::future> 35 | requestDevice(std::optional> descriptor); 36 | 37 | std::unordered_set getFeatures(); 38 | std::shared_ptr getLimits(); 39 | std::shared_ptr getInfo(); 40 | bool getIsFallbackAdapter(); 41 | 42 | void loadHybridMethods() override { 43 | registerHybridGetter("__brand", &GPUAdapter::getBrand, this); 44 | registerHybridMethod("requestDevice", &GPUAdapter::requestDevice, this); 45 | registerHybridGetter("features", &GPUAdapter::getFeatures, this); 46 | registerHybridGetter("limits", &GPUAdapter::getLimits, this); 47 | registerHybridGetter("info", &GPUAdapter::getInfo, this); 48 | registerHybridGetter("isFallbackAdapter", &GPUAdapter::getIsFallbackAdapter, 49 | this); 50 | } 51 | 52 | inline const wgpu::Adapter get() { return _instance; } 53 | 54 | private: 55 | wgpu::Adapter _instance; 56 | std::shared_ptr _async; 57 | }; 58 | 59 | } // namespace rnwgpu -------------------------------------------------------------------------------- /packages/webgpu/cpp/rnwgpu/api/GPUAdapterInfo.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | #include 5 | 6 | #include "Unions.h" 7 | 8 | #include "RNFHybridObject.h" 9 | 10 | #include "AsyncRunner.h" 11 | #include "Convertors.h" 12 | 13 | #include "webgpu/webgpu_cpp.h" 14 | 15 | namespace rnwgpu { 16 | 17 | namespace m = margelo; 18 | 19 | class GPUAdapterInfo : public m::HybridObject { 20 | public: 21 | explicit GPUAdapterInfo(wgpu::AdapterInfo &info) 22 | : HybridObject("GPUAdapterInfo"), _vendor(info.vendor), 23 | _architecture(info.architecture), _device(info.device), 24 | _description(info.description) {} 25 | 26 | public: 27 | std::string getBrand() { return _name; } 28 | 29 | std::string getVendor() { return _vendor; } 30 | std::string getArchitecture() { return _architecture; } 31 | std::string getDevice() { return _device; } 32 | std::string getDescription() { return _description; } 33 | 34 | void loadHybridMethods() override { 35 | registerHybridGetter("__brand", &GPUAdapterInfo::getBrand, this); 36 | 37 | registerHybridGetter("vendor", &GPUAdapterInfo::getVendor, this); 38 | registerHybridGetter("architecture", &GPUAdapterInfo::getArchitecture, 39 | this); 40 | registerHybridGetter("device", &GPUAdapterInfo::getDevice, this); 41 | registerHybridGetter("description", &GPUAdapterInfo::getDescription, this); 42 | } 43 | 44 | private: 45 | std::string _vendor; 46 | std::string _architecture; 47 | std::string _device; 48 | std::string _description; 49 | }; 50 | 51 | } // namespace rnwgpu 52 | -------------------------------------------------------------------------------- /packages/webgpu/cpp/rnwgpu/api/GPUBindGroup.cpp: -------------------------------------------------------------------------------- 1 | #include "GPUBindGroup.h" 2 | 3 | namespace rnwgpu {} // namespace rnwgpu -------------------------------------------------------------------------------- /packages/webgpu/cpp/rnwgpu/api/GPUBindGroup.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | 5 | #include "Unions.h" 6 | 7 | #include "RNFHybridObject.h" 8 | 9 | #include "AsyncRunner.h" 10 | 11 | #include "webgpu/webgpu_cpp.h" 12 | 13 | namespace rnwgpu { 14 | 15 | namespace m = margelo; 16 | 17 | class GPUBindGroup : public m::HybridObject { 18 | public: 19 | explicit GPUBindGroup(wgpu::BindGroup instance, std::string label) 20 | : HybridObject("GPUBindGroup"), _instance(instance), _label(label) {} 21 | 22 | public: 23 | std::string getBrand() { return _name; } 24 | 25 | std::string getLabel() { return _label; } 26 | void setLabel(const std::string &label) { 27 | _label = label; 28 | _instance.SetLabel(_label.c_str()); 29 | } 30 | 31 | void loadHybridMethods() override { 32 | registerHybridGetter("__brand", &GPUBindGroup::getBrand, this); 33 | 34 | registerHybridGetter("label", &GPUBindGroup::getLabel, this); 35 | registerHybridSetter("label", &GPUBindGroup::setLabel, this); 36 | } 37 | 38 | inline const wgpu::BindGroup get() { return _instance; } 39 | 40 | private: 41 | wgpu::BindGroup _instance; 42 | std::string _label; 43 | }; 44 | 45 | } // namespace rnwgpu -------------------------------------------------------------------------------- /packages/webgpu/cpp/rnwgpu/api/GPUBindGroupLayout.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | 5 | #include "Unions.h" 6 | 7 | #include "RNFHybridObject.h" 8 | 9 | #include "AsyncRunner.h" 10 | 11 | #include "webgpu/webgpu_cpp.h" 12 | 13 | namespace rnwgpu { 14 | 15 | namespace m = margelo; 16 | 17 | class GPUBindGroupLayout : public m::HybridObject { 18 | public: 19 | explicit GPUBindGroupLayout(wgpu::BindGroupLayout instance, std::string label) 20 | : HybridObject("GPUBindGroupLayout"), _instance(instance), _label(label) { 21 | } 22 | 23 | public: 24 | std::string getBrand() { return _name; } 25 | 26 | std::string getLabel() { return _label; } 27 | void setLabel(const std::string &label) { 28 | _label = label; 29 | _instance.SetLabel(_label.c_str()); 30 | } 31 | 32 | void loadHybridMethods() override { 33 | registerHybridGetter("__brand", &GPUBindGroupLayout::getBrand, this); 34 | 35 | registerHybridGetter("label", &GPUBindGroupLayout::getLabel, this); 36 | registerHybridSetter("label", &GPUBindGroupLayout::setLabel, this); 37 | } 38 | 39 | inline const wgpu::BindGroupLayout get() { return _instance; } 40 | 41 | private: 42 | wgpu::BindGroupLayout _instance; 43 | std::string _label; 44 | }; 45 | 46 | } // namespace rnwgpu -------------------------------------------------------------------------------- /packages/webgpu/cpp/rnwgpu/api/GPUCanvasContext.cpp: -------------------------------------------------------------------------------- 1 | #include "GPUCanvasContext.h" 2 | #include "Convertors.h" 3 | #include "RNWebGPUManager.h" 4 | 5 | #ifdef __APPLE__ 6 | #include "dawn/native/MetalBackend.h" 7 | #endif 8 | 9 | namespace rnwgpu { 10 | 11 | void GPUCanvasContext::configure( 12 | std::shared_ptr configuration) { 13 | Convertor conv; 14 | wgpu::SurfaceConfiguration surfaceConfiguration; 15 | surfaceConfiguration.device = configuration->device->get(); 16 | if (configuration->viewFormats.has_value()) { 17 | if (!conv(surfaceConfiguration.viewFormats, 18 | surfaceConfiguration.viewFormatCount, 19 | configuration->viewFormats.value())) { 20 | throw std::runtime_error("Error with SurfaceConfiguration"); 21 | } 22 | } 23 | if (!conv(surfaceConfiguration.usage, configuration->usage) || 24 | !conv(surfaceConfiguration.format, configuration->format)) { 25 | throw std::runtime_error("Error with SurfaceConfiguration"); 26 | } 27 | 28 | #ifdef __APPLE__ 29 | surfaceConfiguration.alphaMode = configuration->alphaMode; 30 | #endif 31 | surfaceConfiguration.presentMode = wgpu::PresentMode::Fifo; 32 | _surfaceInfo->configure(surfaceConfiguration); 33 | } 34 | 35 | void GPUCanvasContext::unconfigure() {} 36 | 37 | std::shared_ptr GPUCanvasContext::getCurrentTexture() { 38 | auto prevSize = _surfaceInfo->getConfig(); 39 | auto width = _canvas->getWidth(); 40 | auto height = _canvas->getHeight(); 41 | auto sizeHasChanged = prevSize.width != width || prevSize.height != height; 42 | if (sizeHasChanged) { 43 | _surfaceInfo->reconfigure(width, height); 44 | } 45 | auto texture = _surfaceInfo->getCurrentTexture(); 46 | return std::make_shared(texture, ""); 47 | } 48 | 49 | void GPUCanvasContext::present() { 50 | #ifdef __APPLE__ 51 | dawn::native::metal::WaitForCommandsToBeScheduled( 52 | _surfaceInfo->getDevice().Get()); 53 | #endif 54 | auto size = _surfaceInfo->getSize(); 55 | _canvas->setClientWidth(size.width); 56 | _canvas->setClientHeight(size.height); 57 | _surfaceInfo->present(); 58 | } 59 | 60 | } // namespace rnwgpu 61 | -------------------------------------------------------------------------------- /packages/webgpu/cpp/rnwgpu/api/GPUCanvasContext.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | #include 5 | 6 | #include "Unions.h" 7 | 8 | #include "webgpu/webgpu_cpp.h" 9 | 10 | #include "RNFHybridObject.h" 11 | 12 | #include "AsyncRunner.h" 13 | 14 | #include "Canvas.h" 15 | #include "GPU.h" 16 | #include "GPUCanvasConfiguration.h" 17 | #include "GPUTexture.h" 18 | #include "SurfaceRegistry.h" 19 | 20 | namespace rnwgpu { 21 | 22 | namespace m = margelo; 23 | 24 | class GPUCanvasContext : public m::HybridObject { 25 | public: 26 | GPUCanvasContext(std::shared_ptr gpu, int contextId, int width, 27 | int height) 28 | : HybridObject("GPUCanvasContext"), _gpu(std::move(gpu)) { 29 | _canvas = std::make_shared(nullptr, width, height); 30 | auto ®istry = rnwgpu::SurfaceRegistry::getInstance(); 31 | _surfaceInfo = 32 | registry.getSurfaceInfoOrCreate(contextId, _gpu->get(), width, height); 33 | } 34 | 35 | public: 36 | std::string getBrand() { return _name; } 37 | 38 | std::shared_ptr getCanvas() { return _canvas; } 39 | 40 | void loadHybridMethods() override { 41 | registerHybridGetter("__brand", &GPUCanvasContext::getBrand, this); 42 | registerHybridGetter("canvas", &GPUCanvasContext::getCanvas, this); 43 | registerHybridMethod("configure", &GPUCanvasContext::configure, this); 44 | registerHybridMethod("unconfigure", &GPUCanvasContext::unconfigure, this); 45 | registerHybridMethod("getCurrentTexture", 46 | &GPUCanvasContext::getCurrentTexture, this); 47 | registerHybridMethod("present", &GPUCanvasContext::present, this); 48 | } 49 | 50 | // TODO: is this ok? 51 | inline const wgpu::Surface get() { return nullptr; } 52 | void configure(std::shared_ptr configuration); 53 | void unconfigure(); 54 | std::shared_ptr getCurrentTexture(); 55 | void present(); 56 | 57 | private: 58 | std::shared_ptr _canvas; 59 | std::shared_ptr _surfaceInfo; 60 | std::shared_ptr _gpu; 61 | }; 62 | 63 | } // namespace rnwgpu 64 | -------------------------------------------------------------------------------- /packages/webgpu/cpp/rnwgpu/api/GPUCommandBuffer.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | 5 | #include "Unions.h" 6 | 7 | #include "RNFHybridObject.h" 8 | 9 | #include "AsyncRunner.h" 10 | 11 | #include "webgpu/webgpu_cpp.h" 12 | 13 | namespace rnwgpu { 14 | 15 | namespace m = margelo; 16 | 17 | class GPUCommandBuffer : public m::HybridObject { 18 | public: 19 | explicit GPUCommandBuffer(wgpu::CommandBuffer instance, std::string label) 20 | : HybridObject("GPUCommandBuffer"), _instance(instance), _label(label) {} 21 | 22 | public: 23 | std::string getBrand() { return _name; } 24 | 25 | std::string getLabel() { return _label; } 26 | void setLabel(const std::string &label) { 27 | _label = label; 28 | _instance.SetLabel(_label.c_str()); 29 | } 30 | 31 | void loadHybridMethods() override { 32 | registerHybridGetter("__brand", &GPUCommandBuffer::getBrand, this); 33 | 34 | registerHybridGetter("label", &GPUCommandBuffer::getLabel, this); 35 | registerHybridSetter("label", &GPUCommandBuffer::setLabel, this); 36 | } 37 | 38 | inline const wgpu::CommandBuffer get() { return _instance; } 39 | 40 | private: 41 | wgpu::CommandBuffer _instance; 42 | std::string _label; 43 | }; 44 | 45 | } // namespace rnwgpu -------------------------------------------------------------------------------- /packages/webgpu/cpp/rnwgpu/api/GPUCompilationMessage.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | 5 | #include "Unions.h" 6 | 7 | #include "RNFHybridObject.h" 8 | 9 | #include "AsyncRunner.h" 10 | 11 | #include "webgpu/webgpu_cpp.h" 12 | 13 | namespace rnwgpu { 14 | 15 | namespace m = margelo; 16 | 17 | class GPUCompilationMessage : public m::HybridObject { 18 | public: 19 | explicit GPUCompilationMessage(wgpu::CompilationMessage instance) 20 | : HybridObject("GPUCompilationMessage"), _instance(instance) {} 21 | 22 | public: 23 | std::string getBrand() { return _name; } 24 | 25 | void loadHybridMethods() override { 26 | registerHybridGetter("__brand", &GPUCompilationMessage::getBrand, this); 27 | } 28 | 29 | inline const wgpu::CompilationMessage get() { return _instance; } 30 | 31 | private: 32 | wgpu::CompilationMessage _instance; 33 | }; 34 | 35 | } // namespace rnwgpu -------------------------------------------------------------------------------- /packages/webgpu/cpp/rnwgpu/api/GPUComputePipeline.cpp: -------------------------------------------------------------------------------- 1 | #include "GPUComputePipeline.h" 2 | 3 | namespace rnwgpu { 4 | 5 | std::shared_ptr 6 | GPUComputePipeline::getBindGroupLayout(uint32_t groupIndex) { 7 | auto bindGroup = _instance.GetBindGroupLayout(groupIndex); 8 | return std::make_shared(bindGroup, ""); 9 | } 10 | 11 | } // namespace rnwgpu -------------------------------------------------------------------------------- /packages/webgpu/cpp/rnwgpu/api/GPUComputePipeline.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | #include 5 | 6 | #include "Unions.h" 7 | 8 | #include "RNFHybridObject.h" 9 | 10 | #include "AsyncRunner.h" 11 | 12 | #include "webgpu/webgpu_cpp.h" 13 | 14 | #include "GPUBindGroupLayout.h" 15 | 16 | namespace rnwgpu { 17 | 18 | namespace m = margelo; 19 | 20 | class GPUComputePipeline : public m::HybridObject { 21 | public: 22 | explicit GPUComputePipeline(wgpu::ComputePipeline instance, std::string label) 23 | : HybridObject("GPUComputePipeline"), _instance(instance), _label(label) { 24 | } 25 | 26 | public: 27 | std::string getBrand() { return _name; } 28 | 29 | std::shared_ptr getBindGroupLayout(uint32_t index); 30 | 31 | std::string getLabel() { return _label; } 32 | void setLabel(const std::string &label) { 33 | _label = label; 34 | _instance.SetLabel(_label.c_str()); 35 | } 36 | 37 | void loadHybridMethods() override { 38 | registerHybridGetter("__brand", &GPUComputePipeline::getBrand, this); 39 | registerHybridMethod("getBindGroupLayout", 40 | &GPUComputePipeline::getBindGroupLayout, this); 41 | 42 | registerHybridGetter("label", &GPUComputePipeline::getLabel, this); 43 | registerHybridSetter("label", &GPUComputePipeline::setLabel, this); 44 | } 45 | 46 | inline const wgpu::ComputePipeline get() { return _instance; } 47 | 48 | private: 49 | wgpu::ComputePipeline _instance; 50 | std::string _label; 51 | friend class GPUDevice; 52 | }; 53 | 54 | } // namespace rnwgpu -------------------------------------------------------------------------------- /packages/webgpu/cpp/rnwgpu/api/GPUDeviceLostInfo.cpp: -------------------------------------------------------------------------------- 1 | #include "GPUDeviceLostInfo.h" 2 | 3 | namespace rnwgpu { 4 | wgpu::DeviceLostReason getReason(); 5 | std::string getMessage(); 6 | } // namespace rnwgpu -------------------------------------------------------------------------------- /packages/webgpu/cpp/rnwgpu/api/GPUDeviceLostInfo.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | 5 | #include "Unions.h" 6 | 7 | #include "RNFHybridObject.h" 8 | 9 | #include "AsyncRunner.h" 10 | 11 | #include "webgpu/webgpu_cpp.h" 12 | 13 | namespace rnwgpu { 14 | 15 | namespace m = margelo; 16 | 17 | class GPUDeviceLostInfo : public m::HybridObject { 18 | public: 19 | explicit GPUDeviceLostInfo(wgpu::DeviceLostReason reason, std::string message) 20 | : HybridObject("GPUDeviceLostInfo"), _reason(reason), _message(message) {} 21 | 22 | public: 23 | std::string getBrand() { return _name; } 24 | 25 | wgpu::DeviceLostReason getReason() { return _reason; } 26 | std::string getMessage() { return _message; } 27 | 28 | void loadHybridMethods() override { 29 | registerHybridGetter("__brand", &GPUDeviceLostInfo::getBrand, this); 30 | 31 | registerHybridGetter("reason", &GPUDeviceLostInfo::getReason, this); 32 | registerHybridGetter("message", &GPUDeviceLostInfo::getMessage, this); 33 | } 34 | 35 | private: 36 | wgpu::DeviceLostReason _reason; 37 | std::string _message; 38 | }; 39 | 40 | } // namespace rnwgpu -------------------------------------------------------------------------------- /packages/webgpu/cpp/rnwgpu/api/GPUError.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | 5 | #include "webgpu/webgpu_cpp.h" 6 | 7 | #include "RNFEnumMapper.h" 8 | #include "RNFJSIConverter.h" 9 | 10 | namespace rnwgpu { 11 | 12 | class GPUError { 13 | 14 | public: 15 | GPUError(wgpu::ErrorType aType, char const *aMessage) 16 | : type(aType), message(aMessage) {} 17 | 18 | wgpu::ErrorType type; 19 | char const *message; 20 | }; 21 | 22 | } // namespace rnwgpu 23 | 24 | namespace margelo { 25 | 26 | using namespace rnwgpu; // NOLINT(build/namespaces) 27 | 28 | template <> struct JSIConverter> { 29 | static std::shared_ptr 30 | fromJSI(jsi::Runtime &runtime, const jsi::Value &arg, bool outOfBounds) { 31 | throw std::runtime_error("Invalid GPUBindGroupEntry::fromJSI()"); 32 | } 33 | static jsi::Value toJSI(jsi::Runtime &runtime, 34 | std::shared_ptr arg) { 35 | jsi::Object result(runtime); 36 | result.setProperty(runtime, "message", 37 | jsi::String::createFromUtf8(runtime, arg->message)); 38 | return result; 39 | } 40 | }; 41 | 42 | } // namespace margelo 43 | -------------------------------------------------------------------------------- /packages/webgpu/cpp/rnwgpu/api/GPUExternalTexture.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | 5 | #include "Unions.h" 6 | 7 | #include "RNFHybridObject.h" 8 | 9 | #include "AsyncRunner.h" 10 | 11 | #include "webgpu/webgpu_cpp.h" 12 | 13 | namespace rnwgpu { 14 | 15 | namespace m = margelo; 16 | 17 | class GPUExternalTexture : public m::HybridObject { 18 | public: 19 | explicit GPUExternalTexture(wgpu::ExternalTexture instance, std::string label) 20 | : HybridObject("GPUExternalTexture"), _instance(instance), _label(label) { 21 | } 22 | 23 | public: 24 | std::string getBrand() { return _name; } 25 | 26 | std::string getLabel() { return _label; } 27 | void setLabel(const std::string &label) { 28 | _label = label; 29 | _instance.SetLabel(_label.c_str()); 30 | } 31 | 32 | void loadHybridMethods() override { 33 | registerHybridGetter("__brand", &GPUExternalTexture::getBrand, this); 34 | 35 | registerHybridGetter("label", &GPUExternalTexture::getLabel, this); 36 | registerHybridSetter("label", &GPUExternalTexture::setLabel, this); 37 | } 38 | 39 | inline const wgpu::ExternalTexture get() { return _instance; } 40 | 41 | private: 42 | wgpu::ExternalTexture _instance; 43 | std::string _label; 44 | }; 45 | 46 | } // namespace rnwgpu -------------------------------------------------------------------------------- /packages/webgpu/cpp/rnwgpu/api/GPUOrigin2D.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | 5 | #include "RNFJSIConverter.h" 6 | 7 | #include "webgpu/webgpu_cpp.h" 8 | 9 | namespace rnwgpu { 10 | 11 | struct GPUOrigin2D { 12 | double x = 0; 13 | double y = 0; 14 | }; 15 | 16 | } // namespace rnwgpu 17 | 18 | namespace margelo { 19 | 20 | template <> struct JSIConverter> { 21 | static std::shared_ptr 22 | fromJSI(jsi::Runtime &runtime, const jsi::Value &arg, bool outOfBounds) { 23 | auto result = std::make_unique(); 24 | if (!outOfBounds && arg.isObject()) { 25 | if (arg.getObject(runtime).isArray(runtime)) { 26 | auto array = arg.getObject(runtime).asArray(runtime); 27 | auto size = array.size(runtime); 28 | if (size == 0) { 29 | throw std::runtime_error( 30 | "Expected an array of size >1 for GPUTExtent2D"); 31 | } 32 | if (size > 0) { 33 | result->x = array.getValueAtIndex(runtime, 0).asNumber(); 34 | } 35 | if (size > 1) { 36 | result->y = array.getValueAtIndex(runtime, 1).asNumber(); 37 | } 38 | } else { 39 | auto object = arg.getObject(runtime); 40 | if (object.hasProperty(runtime, "x")) { 41 | result->x = object.getProperty(runtime, "x").asNumber(); 42 | } 43 | if (object.hasProperty(runtime, "y")) { 44 | result->y = object.getProperty(runtime, "y").asNumber(); 45 | } 46 | } 47 | } else { 48 | throw std::runtime_error("Expected an object for GPUOrigin3D"); 49 | } 50 | return result; 51 | } 52 | static jsi::Value toJSI(jsi::Runtime &runtime, 53 | std::shared_ptr arg) { 54 | // No conversions here 55 | return jsi::Value::null(); 56 | } 57 | }; 58 | 59 | } // namespace margelo 60 | -------------------------------------------------------------------------------- /packages/webgpu/cpp/rnwgpu/api/GPUOrigin3D.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | 5 | #include "RNFJSIConverter.h" 6 | 7 | #include "webgpu/webgpu_cpp.h" 8 | 9 | namespace rnwgpu { 10 | 11 | struct GPUOrigin3D { 12 | double x = 0; 13 | double y = 0; 14 | double z = 0; 15 | }; 16 | 17 | } // namespace rnwgpu 18 | 19 | namespace margelo { 20 | 21 | template <> struct JSIConverter> { 22 | static std::shared_ptr 23 | fromJSI(jsi::Runtime &runtime, const jsi::Value &arg, bool outOfBounds) { 24 | auto result = std::make_unique(); 25 | if (!outOfBounds && arg.isObject()) { 26 | if (arg.getObject(runtime).isArray(runtime)) { 27 | auto array = arg.getObject(runtime).asArray(runtime); 28 | auto size = array.size(runtime); 29 | if (size == 0) { 30 | throw std::runtime_error( 31 | "Expected an array of size >1 for GPUTExtent3D"); 32 | } 33 | if (size > 0) { 34 | result->x = array.getValueAtIndex(runtime, 0).asNumber(); 35 | } 36 | if (size > 1) { 37 | result->y = array.getValueAtIndex(runtime, 1).asNumber(); 38 | } 39 | if (size > 2) { 40 | result->z = array.getValueAtIndex(runtime, 2).asNumber(); 41 | } 42 | } else { 43 | auto object = arg.getObject(runtime); 44 | if (object.hasProperty(runtime, "x")) { 45 | result->x = object.getProperty(runtime, "x").asNumber(); 46 | } 47 | if (object.hasProperty(runtime, "y")) { 48 | result->y = object.getProperty(runtime, "y").asNumber(); 49 | } 50 | if (object.hasProperty(runtime, "z")) { 51 | result->z = object.getProperty(runtime, "z").asNumber(); 52 | } 53 | } 54 | } else { 55 | throw std::runtime_error("Expected an object for GPUOrigin3D"); 56 | } 57 | return result; 58 | } 59 | static jsi::Value toJSI(jsi::Runtime &runtime, 60 | std::shared_ptr arg) { 61 | // No conversions here 62 | return jsi::Value::null(); 63 | } 64 | }; 65 | 66 | } // namespace margelo 67 | -------------------------------------------------------------------------------- /packages/webgpu/cpp/rnwgpu/api/GPUPipelineLayout.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | 5 | #include "Unions.h" 6 | 7 | #include "RNFHybridObject.h" 8 | 9 | #include "AsyncRunner.h" 10 | 11 | #include "webgpu/webgpu_cpp.h" 12 | 13 | namespace rnwgpu { 14 | 15 | namespace m = margelo; 16 | 17 | class GPUPipelineLayout : public m::HybridObject { 18 | public: 19 | explicit GPUPipelineLayout(wgpu::PipelineLayout instance, std::string label) 20 | : HybridObject("GPUPipelineLayout"), _instance(instance), _label(label) {} 21 | 22 | public: 23 | std::string getBrand() { return _name; } 24 | 25 | std::string getLabel() { return _label; } 26 | void setLabel(const std::string &label) { 27 | _label = label; 28 | _instance.SetLabel(_label.c_str()); 29 | } 30 | 31 | void loadHybridMethods() override { 32 | registerHybridGetter("__brand", &GPUPipelineLayout::getBrand, this); 33 | 34 | registerHybridGetter("label", &GPUPipelineLayout::getLabel, this); 35 | registerHybridSetter("label", &GPUPipelineLayout::setLabel, this); 36 | } 37 | 38 | inline const wgpu::PipelineLayout get() { return _instance; } 39 | 40 | private: 41 | wgpu::PipelineLayout _instance; 42 | std::string _label; 43 | }; 44 | 45 | } // namespace rnwgpu -------------------------------------------------------------------------------- /packages/webgpu/cpp/rnwgpu/api/GPUQuerySet.cpp: -------------------------------------------------------------------------------- 1 | #include "GPUQuerySet.h" 2 | 3 | namespace rnwgpu { 4 | 5 | void GPUQuerySet::destroy() { _instance.Destroy(); } 6 | 7 | wgpu::QueryType GPUQuerySet::getType() { return _instance.GetType(); } 8 | 9 | uint32_t GPUQuerySet::getCount() { return _instance.GetCount(); } 10 | 11 | } // namespace rnwgpu -------------------------------------------------------------------------------- /packages/webgpu/cpp/rnwgpu/api/GPUQuerySet.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | 5 | #include "Unions.h" 6 | 7 | #include "RNFHybridObject.h" 8 | 9 | #include "AsyncRunner.h" 10 | 11 | #include "webgpu/webgpu_cpp.h" 12 | 13 | namespace rnwgpu { 14 | 15 | namespace m = margelo; 16 | 17 | class GPUQuerySet : public m::HybridObject { 18 | public: 19 | explicit GPUQuerySet(wgpu::QuerySet instance, std::string label) 20 | : HybridObject("GPUQuerySet"), _instance(instance), _label(label) {} 21 | 22 | public: 23 | std::string getBrand() { return _name; } 24 | 25 | void destroy(); 26 | 27 | wgpu::QueryType getType(); 28 | uint32_t getCount(); 29 | 30 | std::string getLabel() { return _label; } 31 | void setLabel(const std::string &label) { 32 | _label = label; 33 | _instance.SetLabel(_label.c_str()); 34 | } 35 | 36 | void loadHybridMethods() override { 37 | registerHybridGetter("__brand", &GPUQuerySet::getBrand, this); 38 | registerHybridMethod("destroy", &GPUQuerySet::destroy, this); 39 | registerHybridGetter("type", &GPUQuerySet::getType, this); 40 | registerHybridGetter("count", &GPUQuerySet::getCount, this); 41 | registerHybridGetter("label", &GPUQuerySet::getLabel, this); 42 | registerHybridSetter("label", &GPUQuerySet::setLabel, this); 43 | } 44 | 45 | inline const wgpu::QuerySet get() { return _instance; } 46 | 47 | private: 48 | wgpu::QuerySet _instance; 49 | std::string _label; 50 | }; 51 | 52 | } // namespace rnwgpu -------------------------------------------------------------------------------- /packages/webgpu/cpp/rnwgpu/api/GPURenderBundle.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | 5 | #include "Unions.h" 6 | 7 | #include "RNFHybridObject.h" 8 | 9 | #include "AsyncRunner.h" 10 | 11 | #include "webgpu/webgpu_cpp.h" 12 | 13 | namespace rnwgpu { 14 | 15 | namespace m = margelo; 16 | 17 | class GPURenderBundle : public m::HybridObject { 18 | public: 19 | explicit GPURenderBundle(wgpu::RenderBundle instance, std::string label) 20 | : HybridObject("GPURenderBundle"), _instance(instance), _label(label) {} 21 | 22 | public: 23 | std::string getBrand() { return _name; } 24 | 25 | std::string getLabel() { return _label; } 26 | void setLabel(const std::string &label) { 27 | _label = label; 28 | _instance.SetLabel(_label.c_str()); 29 | } 30 | 31 | void loadHybridMethods() override { 32 | registerHybridGetter("__brand", &GPURenderBundle::getBrand, this); 33 | 34 | registerHybridGetter("label", &GPURenderBundle::getLabel, this); 35 | registerHybridSetter("label", &GPURenderBundle::setLabel, this); 36 | } 37 | 38 | inline const wgpu::RenderBundle get() { return _instance; } 39 | 40 | private: 41 | wgpu::RenderBundle _instance; 42 | std::string _label; 43 | }; 44 | 45 | } // namespace rnwgpu -------------------------------------------------------------------------------- /packages/webgpu/cpp/rnwgpu/api/GPURenderPipeline.cpp: -------------------------------------------------------------------------------- 1 | #include "GPURenderPipeline.h" 2 | 3 | #include 4 | 5 | namespace rnwgpu { 6 | 7 | std::shared_ptr 8 | GPURenderPipeline::getBindGroupLayout(uint32_t groupIndex) { 9 | auto bindGroupLayout = _instance.GetBindGroupLayout(groupIndex); 10 | return std::make_shared(bindGroupLayout, ""); 11 | } 12 | 13 | } // namespace rnwgpu -------------------------------------------------------------------------------- /packages/webgpu/cpp/rnwgpu/api/GPURenderPipeline.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | #include 5 | 6 | #include "Unions.h" 7 | 8 | #include "RNFHybridObject.h" 9 | 10 | #include "AsyncRunner.h" 11 | 12 | #include "webgpu/webgpu_cpp.h" 13 | 14 | #include "GPUBindGroupLayout.h" 15 | 16 | namespace rnwgpu { 17 | 18 | namespace m = margelo; 19 | 20 | class GPURenderPipeline : public m::HybridObject { 21 | public: 22 | explicit GPURenderPipeline(wgpu::RenderPipeline instance, std::string label) 23 | : HybridObject("GPURenderPipeline"), _instance(instance), _label(label) {} 24 | 25 | public: 26 | std::string getBrand() { return _name; } 27 | 28 | std::shared_ptr getBindGroupLayout(uint32_t index); 29 | 30 | std::string getLabel() { return _label; } 31 | void setLabel(const std::string &label) { 32 | _label = label; 33 | _instance.SetLabel(_label.c_str()); 34 | } 35 | 36 | void loadHybridMethods() override { 37 | registerHybridGetter("__brand", &GPURenderPipeline::getBrand, this); 38 | registerHybridMethod("getBindGroupLayout", 39 | &GPURenderPipeline::getBindGroupLayout, this); 40 | 41 | registerHybridGetter("label", &GPURenderPipeline::getLabel, this); 42 | registerHybridSetter("label", &GPURenderPipeline::setLabel, this); 43 | } 44 | 45 | inline const wgpu::RenderPipeline get() { return _instance; } 46 | 47 | private: 48 | wgpu::RenderPipeline _instance; 49 | std::string _label; 50 | friend class GPUDevice; 51 | }; 52 | 53 | } // namespace rnwgpu -------------------------------------------------------------------------------- /packages/webgpu/cpp/rnwgpu/api/GPUSampler.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | 5 | #include "Unions.h" 6 | 7 | #include "RNFHybridObject.h" 8 | 9 | #include "AsyncRunner.h" 10 | 11 | #include "webgpu/webgpu_cpp.h" 12 | 13 | namespace rnwgpu { 14 | 15 | namespace m = margelo; 16 | 17 | class GPUSampler : public m::HybridObject { 18 | public: 19 | explicit GPUSampler(wgpu::Sampler instance, std::string label) 20 | : HybridObject("GPUSampler"), _instance(instance), _label(label) {} 21 | 22 | public: 23 | std::string getBrand() { return _name; } 24 | 25 | std::string getLabel() { return _label; } 26 | void setLabel(const std::string &label) { 27 | _label = label; 28 | _instance.SetLabel(_label.c_str()); 29 | } 30 | 31 | void loadHybridMethods() override { 32 | registerHybridGetter("__brand", &GPUSampler::getBrand, this); 33 | 34 | registerHybridGetter("label", &GPUSampler::getLabel, this); 35 | registerHybridSetter("label", &GPUSampler::setLabel, this); 36 | } 37 | 38 | inline const wgpu::Sampler get() { return _instance; } 39 | 40 | private: 41 | wgpu::Sampler _instance; 42 | std::string _label; 43 | }; 44 | 45 | } // namespace rnwgpu -------------------------------------------------------------------------------- /packages/webgpu/cpp/rnwgpu/api/GPUShaderModule.cpp: -------------------------------------------------------------------------------- 1 | #include "GPUShaderModule.h" 2 | 3 | #include 4 | 5 | namespace rnwgpu { 6 | 7 | std::future> 8 | GPUShaderModule::getCompilationInfo() { 9 | return _async->runAsync([=](wgpu::Instance *instance) { 10 | wgpu::CompilationInfo compilationInfo; 11 | auto result = std::make_shared(); 12 | auto future = _instance.GetCompilationInfo( 13 | wgpu::CallbackMode::WaitAnyOnly, 14 | [&result](wgpu::CompilationInfoRequestStatus status, 15 | wgpu::CompilationInfo const *compilationInfo) { 16 | if (status == wgpu::CompilationInfoRequestStatus::Success && 17 | compilationInfo) { 18 | for (size_t i = 0; i < compilationInfo->messageCount; ++i) { 19 | const auto &wgpuMessage = compilationInfo->messages[i]; 20 | GPUCompilationMessage message; 21 | message.message = 22 | wgpuMessage.message.length ? wgpuMessage.message.data : ""; 23 | message.type = wgpuMessage.type; 24 | message.lineNum = wgpuMessage.lineNum; 25 | message.linePos = wgpuMessage.linePos; 26 | message.offset = wgpuMessage.offset; 27 | message.length = wgpuMessage.length; 28 | result->_messages.push_back(std::move(message)); 29 | } 30 | } 31 | }); 32 | instance->WaitAny(future, UINT64_MAX); 33 | return result; 34 | }); 35 | } 36 | 37 | } // namespace rnwgpu 38 | -------------------------------------------------------------------------------- /packages/webgpu/cpp/rnwgpu/api/GPUShaderModule.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | #include 5 | #include 6 | 7 | #include "Unions.h" 8 | 9 | #include "RNFHybridObject.h" 10 | 11 | #include "AsyncRunner.h" 12 | 13 | #include "webgpu/webgpu_cpp.h" 14 | 15 | #include "GPUCompilationInfo.h" 16 | 17 | namespace rnwgpu { 18 | 19 | namespace m = margelo; 20 | 21 | class GPUShaderModule : public m::HybridObject { 22 | public: 23 | explicit GPUShaderModule(wgpu::ShaderModule instance, 24 | std::shared_ptr async, 25 | std::string label) 26 | : HybridObject("GPUShaderModule"), _instance(instance), _async(async), 27 | _label(label) {} 28 | 29 | public: 30 | std::string getBrand() { return _name; } 31 | 32 | std::future> getCompilationInfo(); 33 | 34 | std::string getLabel() { return _label; } 35 | void setLabel(const std::string &label) { 36 | _label = label; 37 | _instance.SetLabel(_label.c_str()); 38 | } 39 | 40 | void loadHybridMethods() override { 41 | registerHybridGetter("__brand", &GPUShaderModule::getBrand, this); 42 | registerHybridMethod("getCompilationInfo", 43 | &GPUShaderModule::getCompilationInfo, this); 44 | 45 | registerHybridGetter("label", &GPUShaderModule::getLabel, this); 46 | registerHybridSetter("label", &GPUShaderModule::setLabel, this); 47 | } 48 | 49 | inline const wgpu::ShaderModule get() { return _instance; } 50 | 51 | private: 52 | wgpu::ShaderModule _instance; 53 | std::shared_ptr _async; 54 | std::string _label; 55 | }; 56 | 57 | } // namespace rnwgpu -------------------------------------------------------------------------------- /packages/webgpu/cpp/rnwgpu/api/GPUTexture.cpp: -------------------------------------------------------------------------------- 1 | #include "GPUTexture.h" 2 | 3 | #include 4 | 5 | #include "Convertors.h" 6 | 7 | namespace rnwgpu { 8 | 9 | void GPUTexture::destroy() { _instance.Destroy(); } 10 | 11 | std::shared_ptr GPUTexture::createView( 12 | std::optional> descriptor) { 13 | wgpu::TextureViewDescriptor desc; 14 | Convertor conv; 15 | if (!conv(desc, descriptor)) { 16 | throw std::runtime_error("GPUTextureView.createView(): couldn't access " 17 | "GPUTextureViewDescriptor"); 18 | } 19 | auto view = _instance.CreateView(&desc); 20 | return std::make_shared( 21 | view, 22 | descriptor.has_value() ? descriptor.value()->label.value_or("") : ""); 23 | } 24 | 25 | uint32_t GPUTexture::getWidth() { return _instance.GetWidth(); } 26 | 27 | uint32_t GPUTexture::getHeight() { return _instance.GetHeight(); } 28 | 29 | uint32_t GPUTexture::getDepthOrArrayLayers() { 30 | return _instance.GetDepthOrArrayLayers(); 31 | } 32 | 33 | uint32_t GPUTexture::getMipLevelCount() { return _instance.GetMipLevelCount(); } 34 | 35 | uint32_t GPUTexture::getSampleCount() { return _instance.GetSampleCount(); } 36 | 37 | wgpu::TextureDimension GPUTexture::getDimension() { 38 | return _instance.GetDimension(); 39 | } 40 | 41 | wgpu::TextureFormat GPUTexture::getFormat() { return _instance.GetFormat(); } 42 | 43 | double GPUTexture::getUsage() { 44 | return static_cast(_instance.GetUsage()); 45 | } 46 | 47 | } // namespace rnwgpu 48 | -------------------------------------------------------------------------------- /packages/webgpu/cpp/rnwgpu/api/GPUTextureView.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | 5 | #include "Unions.h" 6 | 7 | #include "RNFHybridObject.h" 8 | 9 | #include "AsyncRunner.h" 10 | 11 | #include "webgpu/webgpu_cpp.h" 12 | 13 | namespace rnwgpu { 14 | 15 | namespace m = margelo; 16 | 17 | class GPUTextureView : public m::HybridObject { 18 | public: 19 | explicit GPUTextureView(wgpu::TextureView instance, std::string label) 20 | : HybridObject("GPUTextureView"), _instance(instance), _label(label) {} 21 | 22 | public: 23 | std::string getBrand() { return _name; } 24 | 25 | std::string getLabel() { return _label; } 26 | void setLabel(const std::string &label) { 27 | _label = label; 28 | _instance.SetLabel(_label.c_str()); 29 | } 30 | 31 | void loadHybridMethods() override { 32 | registerHybridGetter("__brand", &GPUTextureView::getBrand, this); 33 | 34 | registerHybridGetter("label", &GPUTextureView::getLabel, this); 35 | registerHybridSetter("label", &GPUTextureView::setLabel, this); 36 | } 37 | 38 | inline const wgpu::TextureView get() { return _instance; } 39 | 40 | private: 41 | wgpu::TextureView _instance; 42 | std::string _label; 43 | }; 44 | 45 | } // namespace rnwgpu -------------------------------------------------------------------------------- /packages/webgpu/cpp/rnwgpu/api/ImageBitmap.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | 5 | #include "webgpu/webgpu_cpp.h" 6 | 7 | #include "PlatformContext.h" 8 | #include "RNFHybridObject.h" 9 | 10 | namespace rnwgpu { 11 | 12 | class ImageBitmap : public margelo::HybridObject { 13 | public: 14 | explicit ImageBitmap(ImageData &imageData) 15 | : HybridObject("ImageBitmap"), _imageData(imageData) {} 16 | 17 | size_t getWidth() { return _imageData.width; } 18 | 19 | size_t getHeight() { return _imageData.height; } 20 | 21 | void *getData() { return _imageData.data.data(); } 22 | 23 | size_t getSize() { return _imageData.data.size(); } 24 | 25 | void loadHybridMethods() override { 26 | registerHybridGetter("width", &ImageBitmap::getWidth, this); 27 | registerHybridGetter("height", &ImageBitmap::getHeight, this); 28 | } 29 | 30 | private: 31 | ImageData _imageData; 32 | }; 33 | 34 | } // namespace rnwgpu 35 | -------------------------------------------------------------------------------- /packages/webgpu/cpp/rnwgpu/api/descriptors/GPUBindGroupLayoutDescriptor.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | #include 5 | #include 6 | 7 | #include "webgpu/webgpu_cpp.h" 8 | 9 | #include "RNFJSIConverter.h" 10 | #include "WGPULogger.h" 11 | 12 | #include "GPUBindGroupLayoutEntry.h" 13 | #include "RNFHybridObject.h" 14 | 15 | namespace jsi = facebook::jsi; 16 | namespace m = margelo; 17 | 18 | namespace rnwgpu { 19 | 20 | struct GPUBindGroupLayoutDescriptor { 21 | std::vector> 22 | entries; // Iterable 23 | std::optional label; // string 24 | }; 25 | 26 | } // namespace rnwgpu 27 | 28 | namespace margelo { 29 | 30 | using namespace rnwgpu; // NOLINT(build/namespaces) 31 | 32 | template <> 33 | struct JSIConverter> { 34 | static std::shared_ptr 35 | fromJSI(jsi::Runtime &runtime, const jsi::Value &arg, bool outOfBounds) { 36 | auto result = std::make_unique(); 37 | if (!outOfBounds && arg.isObject()) { 38 | auto value = arg.getObject(runtime); 39 | if (value.hasProperty(runtime, "entries")) { 40 | auto prop = value.getProperty(runtime, "entries"); 41 | result->entries = JSIConverter>>::fromJSI(runtime, prop, 43 | false); 44 | } 45 | if (value.hasProperty(runtime, "label")) { 46 | auto prop = value.getProperty(runtime, "label"); 47 | result->label = JSIConverter>::fromJSI( 48 | runtime, prop, false); 49 | } 50 | } 51 | 52 | return result; 53 | } 54 | static jsi::Value 55 | toJSI(jsi::Runtime &runtime, 56 | std::shared_ptr arg) { 57 | throw std::runtime_error("Invalid GPUBindGroupLayoutDescriptor::toJSI()"); 58 | } 59 | }; 60 | 61 | } // namespace margelo -------------------------------------------------------------------------------- /packages/webgpu/cpp/rnwgpu/api/descriptors/GPUBlendComponent.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | 5 | #include "webgpu/webgpu_cpp.h" 6 | 7 | #include "RNFJSIConverter.h" 8 | #include "WGPULogger.h" 9 | 10 | #include "RNFHybridObject.h" 11 | 12 | namespace jsi = facebook::jsi; 13 | namespace m = margelo; 14 | 15 | namespace rnwgpu { 16 | 17 | struct GPUBlendComponent { 18 | std::optional operation; // GPUBlendOperation 19 | std::optional srcFactor; // GPUBlendFactor 20 | std::optional dstFactor; // GPUBlendFactor 21 | }; 22 | 23 | } // namespace rnwgpu 24 | 25 | namespace margelo { 26 | 27 | using namespace rnwgpu; // NOLINT(build/namespaces) 28 | 29 | template <> struct JSIConverter> { 30 | static std::shared_ptr 31 | fromJSI(jsi::Runtime &runtime, const jsi::Value &arg, bool outOfBounds) { 32 | auto result = std::make_unique(); 33 | if (!outOfBounds && arg.isObject()) { 34 | auto value = arg.getObject(runtime); 35 | if (value.hasProperty(runtime, "operation")) { 36 | auto prop = value.getProperty(runtime, "operation"); 37 | result->operation = 38 | JSIConverter>::fromJSI( 39 | runtime, prop, false); 40 | } 41 | if (value.hasProperty(runtime, "srcFactor")) { 42 | auto prop = value.getProperty(runtime, "srcFactor"); 43 | result->srcFactor = 44 | JSIConverter>::fromJSI( 45 | runtime, prop, false); 46 | } 47 | if (value.hasProperty(runtime, "dstFactor")) { 48 | auto prop = value.getProperty(runtime, "dstFactor"); 49 | result->dstFactor = 50 | JSIConverter>::fromJSI( 51 | runtime, prop, false); 52 | } 53 | } 54 | 55 | return result; 56 | } 57 | static jsi::Value toJSI(jsi::Runtime &runtime, 58 | std::shared_ptr arg) { 59 | throw std::runtime_error("Invalid GPUBlendComponent::toJSI()"); 60 | } 61 | }; 62 | 63 | } // namespace margelo -------------------------------------------------------------------------------- /packages/webgpu/cpp/rnwgpu/api/descriptors/GPUBlendState.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | 5 | #include "webgpu/webgpu_cpp.h" 6 | 7 | #include "RNFJSIConverter.h" 8 | #include "WGPULogger.h" 9 | 10 | #include "GPUBlendComponent.h" 11 | #include "RNFHybridObject.h" 12 | 13 | namespace jsi = facebook::jsi; 14 | namespace m = margelo; 15 | 16 | namespace rnwgpu { 17 | 18 | struct GPUBlendState { 19 | std::shared_ptr color; // GPUBlendComponent 20 | std::shared_ptr alpha; // GPUBlendComponent 21 | }; 22 | 23 | } // namespace rnwgpu 24 | 25 | namespace margelo { 26 | 27 | using namespace rnwgpu; // NOLINT(build/namespaces) 28 | 29 | template <> struct JSIConverter> { 30 | static std::shared_ptr 31 | fromJSI(jsi::Runtime &runtime, const jsi::Value &arg, bool outOfBounds) { 32 | auto result = std::make_unique(); 33 | if (!outOfBounds && arg.isObject()) { 34 | auto value = arg.getObject(runtime); 35 | if (value.hasProperty(runtime, "color")) { 36 | auto prop = value.getProperty(runtime, "color"); 37 | result->color = 38 | JSIConverter>::fromJSI( 39 | runtime, prop, false); 40 | } 41 | if (value.hasProperty(runtime, "alpha")) { 42 | auto prop = value.getProperty(runtime, "alpha"); 43 | result->alpha = 44 | JSIConverter>::fromJSI( 45 | runtime, prop, false); 46 | } 47 | } 48 | 49 | return result; 50 | } 51 | static jsi::Value toJSI(jsi::Runtime &runtime, 52 | std::shared_ptr arg) { 53 | throw std::runtime_error("Invalid GPUBlendState::toJSI()"); 54 | } 55 | }; 56 | 57 | } // namespace margelo -------------------------------------------------------------------------------- /packages/webgpu/cpp/rnwgpu/api/descriptors/GPUBufferBinding.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | 5 | #include "webgpu/webgpu_cpp.h" 6 | 7 | #include "RNFJSIConverter.h" 8 | #include "WGPULogger.h" 9 | 10 | #include "GPUBuffer.h" 11 | #include "RNFHybridObject.h" 12 | 13 | namespace jsi = facebook::jsi; 14 | namespace m = margelo; 15 | 16 | namespace rnwgpu { 17 | 18 | struct GPUBufferBinding { 19 | std::shared_ptr buffer; // GPUBuffer 20 | std::optional offset; // GPUSize64 21 | std::optional size; // GPUSize64 22 | }; 23 | 24 | } // namespace rnwgpu 25 | 26 | namespace margelo { 27 | 28 | using namespace rnwgpu; // NOLINT(build/namespaces) 29 | 30 | template <> struct JSIConverter> { 31 | static std::shared_ptr 32 | fromJSI(jsi::Runtime &runtime, const jsi::Value &arg, bool outOfBounds) { 33 | auto result = std::make_unique(); 34 | if (!outOfBounds && arg.isObject()) { 35 | auto value = arg.getObject(runtime); 36 | if (value.hasProperty(runtime, "buffer")) { 37 | auto prop = value.getProperty(runtime, "buffer"); 38 | result->buffer = JSIConverter>::fromJSI( 39 | runtime, prop, false); 40 | } 41 | if (value.hasProperty(runtime, "offset")) { 42 | auto prop = value.getProperty(runtime, "offset"); 43 | result->offset = 44 | JSIConverter>::fromJSI(runtime, prop, false); 45 | } 46 | if (value.hasProperty(runtime, "size")) { 47 | auto prop = value.getProperty(runtime, "size"); 48 | result->size = 49 | JSIConverter>::fromJSI(runtime, prop, false); 50 | } 51 | } 52 | 53 | return result; 54 | } 55 | static jsi::Value toJSI(jsi::Runtime &runtime, 56 | std::shared_ptr arg) { 57 | throw std::runtime_error("Invalid GPUBufferBinding::toJSI()"); 58 | } 59 | }; 60 | 61 | } // namespace margelo -------------------------------------------------------------------------------- /packages/webgpu/cpp/rnwgpu/api/descriptors/GPUBufferBindingLayout.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | 5 | #include "webgpu/webgpu_cpp.h" 6 | 7 | #include "RNFJSIConverter.h" 8 | #include "WGPULogger.h" 9 | 10 | #include "RNFHybridObject.h" 11 | 12 | namespace jsi = facebook::jsi; 13 | namespace m = margelo; 14 | 15 | namespace rnwgpu { 16 | 17 | struct GPUBufferBindingLayout { 18 | std::optional type; // GPUBufferBindingType 19 | std::optional hasDynamicOffset; // boolean 20 | std::optional minBindingSize; // GPUSize64 21 | }; 22 | 23 | } // namespace rnwgpu 24 | 25 | namespace margelo { 26 | 27 | using namespace rnwgpu; // NOLINT(build/namespaces) 28 | 29 | template <> 30 | struct JSIConverter> { 31 | static std::shared_ptr 32 | fromJSI(jsi::Runtime &runtime, const jsi::Value &arg, bool outOfBounds) { 33 | auto result = std::make_unique(); 34 | if (!outOfBounds && arg.isObject()) { 35 | auto value = arg.getObject(runtime); 36 | if (value.hasProperty(runtime, "type")) { 37 | auto prop = value.getProperty(runtime, "type"); 38 | result->type = 39 | JSIConverter>::fromJSI( 40 | runtime, prop, false); 41 | } 42 | if (value.hasProperty(runtime, "hasDynamicOffset")) { 43 | auto prop = value.getProperty(runtime, "hasDynamicOffset"); 44 | result->hasDynamicOffset = 45 | JSIConverter>::fromJSI(runtime, prop, false); 46 | } 47 | if (value.hasProperty(runtime, "minBindingSize")) { 48 | auto prop = value.getProperty(runtime, "minBindingSize"); 49 | result->minBindingSize = 50 | JSIConverter>::fromJSI(runtime, prop, false); 51 | } 52 | } 53 | 54 | return result; 55 | } 56 | static jsi::Value toJSI(jsi::Runtime &runtime, 57 | std::shared_ptr arg) { 58 | throw std::runtime_error("Invalid GPUBufferBindingLayout::toJSI()"); 59 | } 60 | }; 61 | 62 | } // namespace margelo -------------------------------------------------------------------------------- /packages/webgpu/cpp/rnwgpu/api/descriptors/GPUBufferUsage.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include 3 | 4 | #include 5 | 6 | #include "webgpu/webgpu_cpp.h" 7 | 8 | namespace rnwgpu { 9 | 10 | namespace m = margelo; 11 | 12 | class GPUBufferUsage : public m::HybridObject { 13 | public: 14 | GPUBufferUsage() : HybridObject("GPUBufferUsage") {} 15 | 16 | public: 17 | double MapRead() { return static_cast(wgpu::BufferUsage::MapRead); } 18 | double MapWrite() { return static_cast(wgpu::BufferUsage::MapWrite); } 19 | double CopySrc() { return static_cast(wgpu::BufferUsage::CopySrc); } 20 | double CopyDst() { return static_cast(wgpu::BufferUsage::CopyDst); } 21 | double Index() { return static_cast(wgpu::BufferUsage::Index); } 22 | double Vertex() { return static_cast(wgpu::BufferUsage::Vertex); } 23 | double Uniform() { return static_cast(wgpu::BufferUsage::Uniform); } 24 | double Storage() { return static_cast(wgpu::BufferUsage::Storage); } 25 | double Indirect() { return static_cast(wgpu::BufferUsage::Indirect); } 26 | double QueryResolve() { 27 | return static_cast(wgpu::BufferUsage::QueryResolve); 28 | } 29 | 30 | void loadHybridMethods() override { 31 | registerHybridGetter("MAP_READ", &GPUBufferUsage::MapRead, this); 32 | registerHybridGetter("MAP_WRITE", &GPUBufferUsage::MapWrite, this); 33 | registerHybridGetter("COPY_SRC", &GPUBufferUsage::CopySrc, this); 34 | registerHybridGetter("COPY_DST", &GPUBufferUsage::CopyDst, this); 35 | registerHybridGetter("INDEX", &GPUBufferUsage::Index, this); 36 | registerHybridGetter("VERTEX", &GPUBufferUsage::Vertex, this); 37 | registerHybridGetter("UNIFORM", &GPUBufferUsage::Uniform, this); 38 | registerHybridGetter("STORAGE", &GPUBufferUsage::Storage, this); 39 | registerHybridGetter("INDIRECT", &GPUBufferUsage::Indirect, this); 40 | registerHybridGetter("QUERY_RESOLVE", &GPUBufferUsage::QueryResolve, this); 41 | } 42 | }; 43 | } // namespace rnwgpu -------------------------------------------------------------------------------- /packages/webgpu/cpp/rnwgpu/api/descriptors/GPUColorWrite.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include 3 | 4 | #include 5 | 6 | #include "webgpu/webgpu_cpp.h" 7 | 8 | namespace rnwgpu { 9 | 10 | namespace m = margelo; 11 | 12 | class GPUColorWrite : public m::HybridObject { 13 | public: 14 | GPUColorWrite() : HybridObject("GPUColorWrite") {} 15 | 16 | public: 17 | double Red() { return static_cast(wgpu::ColorWriteMask::Red); } 18 | double Green() { return static_cast(wgpu::ColorWriteMask::Green); } 19 | double Blue() { return static_cast(wgpu::ColorWriteMask::Blue); } 20 | double Alpha() { return static_cast(wgpu::ColorWriteMask::Alpha); } 21 | double All() { return static_cast(wgpu::ColorWriteMask::All); } 22 | 23 | void loadHybridMethods() override { 24 | registerHybridGetter("RED", &GPUColorWrite::Red, this); 25 | registerHybridGetter("GREEN", &GPUColorWrite::Green, this); 26 | registerHybridGetter("BLUE", &GPUColorWrite::Blue, this); 27 | registerHybridGetter("ALPHA", &GPUColorWrite::Alpha, this); 28 | registerHybridGetter("ALL", &GPUColorWrite::All, this); 29 | } 30 | }; 31 | } // namespace rnwgpu -------------------------------------------------------------------------------- /packages/webgpu/cpp/rnwgpu/api/descriptors/GPUCommandBufferDescriptor.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | #include 5 | 6 | #include "webgpu/webgpu_cpp.h" 7 | 8 | #include "RNFJSIConverter.h" 9 | #include "WGPULogger.h" 10 | 11 | #include "RNFHybridObject.h" 12 | 13 | namespace jsi = facebook::jsi; 14 | namespace m = margelo; 15 | 16 | namespace rnwgpu { 17 | 18 | struct GPUCommandBufferDescriptor { 19 | std::optional label; // string 20 | }; 21 | 22 | } // namespace rnwgpu 23 | 24 | namespace margelo { 25 | 26 | using namespace rnwgpu; // NOLINT(build/namespaces) 27 | 28 | template <> 29 | struct JSIConverter> { 30 | static std::shared_ptr 31 | fromJSI(jsi::Runtime &runtime, const jsi::Value &arg, bool outOfBounds) { 32 | auto result = std::make_unique(); 33 | if (!outOfBounds && arg.isObject()) { 34 | auto value = arg.getObject(runtime); 35 | if (value.hasProperty(runtime, "label")) { 36 | auto prop = value.getProperty(runtime, "label"); 37 | result->label = JSIConverter>::fromJSI( 38 | runtime, prop, false); 39 | } 40 | } 41 | 42 | return result; 43 | } 44 | static jsi::Value 45 | toJSI(jsi::Runtime &runtime, 46 | std::shared_ptr arg) { 47 | throw std::runtime_error("Invalid GPUCommandBufferDescriptor::toJSI()"); 48 | } 49 | }; 50 | 51 | } // namespace margelo -------------------------------------------------------------------------------- /packages/webgpu/cpp/rnwgpu/api/descriptors/GPUCommandEncoderDescriptor.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | #include 5 | 6 | #include "webgpu/webgpu_cpp.h" 7 | 8 | #include "RNFJSIConverter.h" 9 | #include "WGPULogger.h" 10 | 11 | #include "RNFHybridObject.h" 12 | 13 | namespace jsi = facebook::jsi; 14 | namespace m = margelo; 15 | 16 | namespace rnwgpu { 17 | 18 | struct GPUCommandEncoderDescriptor { 19 | std::optional label; // string 20 | }; 21 | 22 | } // namespace rnwgpu 23 | 24 | namespace margelo { 25 | 26 | using namespace rnwgpu; // NOLINT(build/namespaces) 27 | 28 | template <> 29 | struct JSIConverter> { 30 | static std::shared_ptr 31 | fromJSI(jsi::Runtime &runtime, const jsi::Value &arg, bool outOfBounds) { 32 | auto result = std::make_unique(); 33 | if (!outOfBounds && arg.isObject()) { 34 | auto value = arg.getObject(runtime); 35 | if (value.hasProperty(runtime, "label")) { 36 | auto prop = value.getProperty(runtime, "label"); 37 | result->label = JSIConverter>::fromJSI( 38 | runtime, prop, false); 39 | } 40 | } 41 | 42 | return result; 43 | } 44 | static jsi::Value 45 | toJSI(jsi::Runtime &runtime, 46 | std::shared_ptr arg) { 47 | throw std::runtime_error("Invalid GPUCommandEncoderDescriptor::toJSI()"); 48 | } 49 | }; 50 | 51 | } // namespace margelo -------------------------------------------------------------------------------- /packages/webgpu/cpp/rnwgpu/api/descriptors/GPUComputePassDescriptor.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | #include 5 | 6 | #include "webgpu/webgpu_cpp.h" 7 | 8 | #include "RNFJSIConverter.h" 9 | #include "WGPULogger.h" 10 | 11 | #include "GPUComputePassTimestampWrites.h" 12 | #include "RNFHybridObject.h" 13 | 14 | namespace jsi = facebook::jsi; 15 | namespace m = margelo; 16 | 17 | namespace rnwgpu { 18 | 19 | struct GPUComputePassDescriptor { 20 | std::optional> 21 | timestampWrites; // GPUComputePassTimestampWrites 22 | std::optional label; // string 23 | }; 24 | 25 | } // namespace rnwgpu 26 | 27 | namespace margelo { 28 | 29 | using namespace rnwgpu; // NOLINT(build/namespaces) 30 | 31 | template <> 32 | struct JSIConverter> { 33 | static std::shared_ptr 34 | fromJSI(jsi::Runtime &runtime, const jsi::Value &arg, bool outOfBounds) { 35 | auto result = std::make_unique(); 36 | if (!outOfBounds && arg.isObject()) { 37 | auto value = arg.getObject(runtime); 38 | if (value.hasProperty(runtime, "timestampWrites")) { 39 | auto prop = value.getProperty(runtime, "timestampWrites"); 40 | result->timestampWrites = JSIConverter>>::fromJSI(runtime, 42 | prop, 43 | false); 44 | } 45 | if (value.hasProperty(runtime, "label")) { 46 | auto prop = value.getProperty(runtime, "label"); 47 | result->label = JSIConverter>::fromJSI( 48 | runtime, prop, false); 49 | } 50 | } 51 | 52 | return result; 53 | } 54 | static jsi::Value 55 | toJSI(jsi::Runtime &runtime, 56 | std::shared_ptr arg) { 57 | throw std::runtime_error("Invalid GPUComputePassDescriptor::toJSI()"); 58 | } 59 | }; 60 | 61 | } // namespace margelo -------------------------------------------------------------------------------- /packages/webgpu/cpp/rnwgpu/api/descriptors/GPUComputePassTimestampWrites.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | 5 | #include "webgpu/webgpu_cpp.h" 6 | 7 | #include "RNFJSIConverter.h" 8 | #include "WGPULogger.h" 9 | 10 | #include "GPUQuerySet.h" 11 | #include "RNFHybridObject.h" 12 | 13 | namespace jsi = facebook::jsi; 14 | namespace m = margelo; 15 | 16 | namespace rnwgpu { 17 | 18 | struct GPUComputePassTimestampWrites { 19 | std::shared_ptr querySet; // GPUQuerySet 20 | std::optional beginningOfPassWriteIndex; // GPUSize32 21 | std::optional endOfPassWriteIndex; // GPUSize32 22 | }; 23 | 24 | } // namespace rnwgpu 25 | 26 | namespace margelo { 27 | 28 | using namespace rnwgpu; // NOLINT(build/namespaces) 29 | 30 | template <> 31 | struct JSIConverter> { 32 | static std::shared_ptr 33 | fromJSI(jsi::Runtime &runtime, const jsi::Value &arg, bool outOfBounds) { 34 | auto result = std::make_unique(); 35 | if (!outOfBounds && arg.isObject()) { 36 | auto value = arg.getObject(runtime); 37 | if (value.hasProperty(runtime, "querySet")) { 38 | auto prop = value.getProperty(runtime, "querySet"); 39 | result->querySet = JSIConverter>::fromJSI( 40 | runtime, prop, false); 41 | } 42 | if (value.hasProperty(runtime, "beginningOfPassWriteIndex")) { 43 | auto prop = value.getProperty(runtime, "beginningOfPassWriteIndex"); 44 | result->beginningOfPassWriteIndex = 45 | JSIConverter>::fromJSI(runtime, prop, false); 46 | } 47 | if (value.hasProperty(runtime, "endOfPassWriteIndex")) { 48 | auto prop = value.getProperty(runtime, "endOfPassWriteIndex"); 49 | result->endOfPassWriteIndex = 50 | JSIConverter>::fromJSI(runtime, prop, false); 51 | } 52 | } 53 | 54 | return result; 55 | } 56 | static jsi::Value 57 | toJSI(jsi::Runtime &runtime, 58 | std::shared_ptr arg) { 59 | throw std::runtime_error("Invalid GPUComputePassTimestampWrites::toJSI()"); 60 | } 61 | }; 62 | 63 | } // namespace margelo -------------------------------------------------------------------------------- /packages/webgpu/cpp/rnwgpu/api/descriptors/GPUExternalTextureBindingLayout.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | 5 | #include "webgpu/webgpu_cpp.h" 6 | 7 | #include "RNFJSIConverter.h" 8 | #include "WGPULogger.h" 9 | 10 | #include "RNFHybridObject.h" 11 | 12 | namespace jsi = facebook::jsi; 13 | namespace m = margelo; 14 | 15 | namespace rnwgpu { 16 | 17 | struct GPUExternalTextureBindingLayout {}; 18 | 19 | } // namespace rnwgpu 20 | 21 | namespace margelo { 22 | 23 | using namespace rnwgpu; // NOLINT(build/namespaces) 24 | 25 | template <> 26 | struct JSIConverter> { 27 | static std::shared_ptr 28 | fromJSI(jsi::Runtime &runtime, const jsi::Value &arg, bool outOfBounds) { 29 | auto result = std::make_unique(); 30 | if (!outOfBounds && arg.isObject()) { 31 | auto value = arg.getObject(runtime); 32 | } 33 | 34 | return result; 35 | } 36 | static jsi::Value 37 | toJSI(jsi::Runtime &runtime, 38 | std::shared_ptr arg) { 39 | throw std::runtime_error( 40 | "Invalid GPUExternalTextureBindingLayout::toJSI()"); 41 | } 42 | }; 43 | 44 | } // namespace margelo -------------------------------------------------------------------------------- /packages/webgpu/cpp/rnwgpu/api/descriptors/GPUImageCopyExternalImage.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | #include 5 | #include 6 | #include 7 | 8 | #include "webgpu/webgpu_cpp.h" 9 | 10 | #include "Convertors.h" 11 | #include "RNFHybridObject.h" 12 | #include "RNFJSIConverter.h" 13 | 14 | #include "GPUOrigin2D.h" 15 | #include "ImageBitmap.h" 16 | 17 | namespace jsi = facebook::jsi; 18 | namespace m = margelo; 19 | 20 | namespace rnwgpu { 21 | 22 | struct GPUImageCopyExternalImage { 23 | std::shared_ptr source; // GPUImageCopyExternalImageSource 24 | std::optional> origin; // GPUOrigin2DStrict 25 | std::optional flipY; // boolean 26 | }; 27 | 28 | } // namespace rnwgpu 29 | 30 | namespace margelo { 31 | 32 | using namespace rnwgpu; // NOLINT(build/namespaces) 33 | 34 | template <> 35 | struct JSIConverter> { 36 | static std::shared_ptr 37 | fromJSI(jsi::Runtime &runtime, const jsi::Value &arg, bool outOfBounds) { 38 | auto result = std::make_unique(); 39 | if (!outOfBounds && arg.isObject()) { 40 | auto obj = arg.getObject(runtime); 41 | if (obj.hasProperty(runtime, "source")) { 42 | auto prop = obj.getProperty(runtime, "source"); 43 | result->source = JSIConverter>::fromJSI( 44 | runtime, prop, false); 45 | } 46 | if (obj.hasProperty(runtime, "origin")) { 47 | auto prop = obj.getProperty(runtime, "origin"); 48 | result->origin = JSIConverter>::fromJSI( 49 | runtime, prop, false); 50 | } 51 | 52 | if (obj.hasProperty(runtime, "flipY")) { 53 | auto prop = obj.getProperty(runtime, "flipY"); 54 | result->flipY = JSIConverter::fromJSI(runtime, prop, false); 55 | } 56 | } 57 | 58 | return result; 59 | } 60 | static jsi::Value 61 | toJSI(jsi::Runtime &runtime, 62 | std::shared_ptr arg) { 63 | throw std::runtime_error("Invalid GPUImageCopyExternalImage::toJSI()"); 64 | } 65 | }; 66 | 67 | } // namespace margelo 68 | -------------------------------------------------------------------------------- /packages/webgpu/cpp/rnwgpu/api/descriptors/GPUImageDataLayout.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | 5 | #include "webgpu/webgpu_cpp.h" 6 | 7 | #include "RNFJSIConverter.h" 8 | #include "WGPULogger.h" 9 | 10 | #include "RNFHybridObject.h" 11 | 12 | namespace jsi = facebook::jsi; 13 | namespace m = margelo; 14 | 15 | namespace rnwgpu { 16 | 17 | struct GPUImageDataLayout { 18 | std::optional offset; // GPUSize64 19 | std::optional bytesPerRow; // GPUSize32 20 | std::optional rowsPerImage; // GPUSize32 21 | }; 22 | 23 | } // namespace rnwgpu 24 | 25 | namespace margelo { 26 | 27 | using namespace rnwgpu; // NOLINT(build/namespaces) 28 | 29 | template <> struct JSIConverter> { 30 | static std::shared_ptr 31 | fromJSI(jsi::Runtime &runtime, const jsi::Value &arg, bool outOfBounds) { 32 | auto result = std::make_unique(); 33 | if (!outOfBounds && arg.isObject()) { 34 | auto value = arg.getObject(runtime); 35 | if (value.hasProperty(runtime, "offset")) { 36 | auto prop = value.getProperty(runtime, "offset"); 37 | result->offset = 38 | JSIConverter>::fromJSI(runtime, prop, false); 39 | } 40 | if (value.hasProperty(runtime, "bytesPerRow")) { 41 | auto prop = value.getProperty(runtime, "bytesPerRow"); 42 | result->bytesPerRow = 43 | JSIConverter>::fromJSI(runtime, prop, false); 44 | } 45 | if (value.hasProperty(runtime, "rowsPerImage")) { 46 | auto prop = value.getProperty(runtime, "rowsPerImage"); 47 | result->rowsPerImage = 48 | JSIConverter>::fromJSI(runtime, prop, false); 49 | } 50 | } 51 | 52 | return result; 53 | } 54 | static jsi::Value toJSI(jsi::Runtime &runtime, 55 | std::shared_ptr arg) { 56 | throw std::runtime_error("Invalid GPUImageDataLayout::toJSI()"); 57 | } 58 | }; 59 | 60 | } // namespace margelo -------------------------------------------------------------------------------- /packages/webgpu/cpp/rnwgpu/api/descriptors/GPUMapMode.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include 3 | 4 | #include 5 | 6 | #include "webgpu/webgpu_cpp.h" 7 | 8 | namespace rnwgpu { 9 | 10 | namespace m = margelo; 11 | 12 | class GPUMapMode : public m::HybridObject { 13 | public: 14 | GPUMapMode() : HybridObject("GPUMapMode") {} 15 | 16 | public: 17 | double Read() { return static_cast(wgpu::MapMode::Read); } 18 | double Write() { return static_cast(wgpu::MapMode::Write); } 19 | 20 | void loadHybridMethods() override { 21 | registerHybridGetter("READ", &GPUMapMode::Read, this); 22 | registerHybridGetter("WRITE", &GPUMapMode::Write, this); 23 | } 24 | }; 25 | } // namespace rnwgpu -------------------------------------------------------------------------------- /packages/webgpu/cpp/rnwgpu/api/descriptors/GPUMultisampleState.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | 5 | #include "webgpu/webgpu_cpp.h" 6 | 7 | #include "RNFJSIConverter.h" 8 | #include "WGPULogger.h" 9 | 10 | #include "RNFHybridObject.h" 11 | 12 | namespace jsi = facebook::jsi; 13 | namespace m = margelo; 14 | 15 | namespace rnwgpu { 16 | 17 | struct GPUMultisampleState { 18 | std::optional count; // GPUSize32 19 | std::optional mask; // GPUSampleMask 20 | std::optional alphaToCoverageEnabled; // boolean 21 | }; 22 | 23 | } // namespace rnwgpu 24 | 25 | namespace margelo { 26 | 27 | using namespace rnwgpu; // NOLINT(build/namespaces) 28 | 29 | template <> struct JSIConverter> { 30 | static std::shared_ptr 31 | fromJSI(jsi::Runtime &runtime, const jsi::Value &arg, bool outOfBounds) { 32 | auto result = std::make_unique(); 33 | if (!outOfBounds && arg.isObject()) { 34 | auto value = arg.getObject(runtime); 35 | if (value.hasProperty(runtime, "count")) { 36 | auto prop = value.getProperty(runtime, "count"); 37 | result->count = 38 | JSIConverter>::fromJSI(runtime, prop, false); 39 | } 40 | if (value.hasProperty(runtime, "mask")) { 41 | auto prop = value.getProperty(runtime, "mask"); 42 | result->mask = 43 | JSIConverter>::fromJSI(runtime, prop, false); 44 | } 45 | if (value.hasProperty(runtime, "alphaToCoverageEnabled")) { 46 | auto prop = value.getProperty(runtime, "alphaToCoverageEnabled"); 47 | result->alphaToCoverageEnabled = 48 | JSIConverter>::fromJSI(runtime, prop, false); 49 | } 50 | } 51 | 52 | return result; 53 | } 54 | static jsi::Value toJSI(jsi::Runtime &runtime, 55 | std::shared_ptr arg) { 56 | throw std::runtime_error("Invalid GPUMultisampleState::toJSI()"); 57 | } 58 | }; 59 | 60 | } // namespace margelo -------------------------------------------------------------------------------- /packages/webgpu/cpp/rnwgpu/api/descriptors/GPUPipelineLayoutDescriptor.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | #include 5 | #include 6 | 7 | #include "webgpu/webgpu_cpp.h" 8 | 9 | #include "RNFJSIConverter.h" 10 | #include "WGPULogger.h" 11 | 12 | #include "GPUBindGroupLayout.h" 13 | #include "RNFHybridObject.h" 14 | 15 | namespace jsi = facebook::jsi; 16 | namespace m = margelo; 17 | 18 | namespace rnwgpu { 19 | 20 | struct GPUPipelineLayoutDescriptor { 21 | std::vector> 22 | bindGroupLayouts; // Iterable 23 | std::optional label; // string 24 | }; 25 | 26 | } // namespace rnwgpu 27 | 28 | namespace margelo { 29 | 30 | using namespace rnwgpu; // NOLINT(build/namespaces) 31 | 32 | template <> 33 | struct JSIConverter> { 34 | static std::shared_ptr 35 | fromJSI(jsi::Runtime &runtime, const jsi::Value &arg, bool outOfBounds) { 36 | auto result = std::make_unique(); 37 | if (!outOfBounds && arg.isObject()) { 38 | auto value = arg.getObject(runtime); 39 | if (value.hasProperty(runtime, "bindGroupLayouts")) { 40 | auto prop = value.getProperty(runtime, "bindGroupLayouts"); 41 | result->bindGroupLayouts = JSIConverter< 42 | std::vector>>::fromJSI(runtime, 43 | prop, 44 | false); 45 | } 46 | if (value.hasProperty(runtime, "label")) { 47 | auto prop = value.getProperty(runtime, "label"); 48 | result->label = JSIConverter>::fromJSI( 49 | runtime, prop, false); 50 | } 51 | } 52 | 53 | return result; 54 | } 55 | static jsi::Value 56 | toJSI(jsi::Runtime &runtime, 57 | std::shared_ptr arg) { 58 | throw std::runtime_error("Invalid GPUPipelineLayoutDescriptor::toJSI()"); 59 | } 60 | }; 61 | 62 | } // namespace margelo -------------------------------------------------------------------------------- /packages/webgpu/cpp/rnwgpu/api/descriptors/GPUQuerySetDescriptor.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | #include 5 | 6 | #include "webgpu/webgpu_cpp.h" 7 | 8 | #include "RNFJSIConverter.h" 9 | #include "WGPULogger.h" 10 | 11 | #include "RNFHybridObject.h" 12 | 13 | namespace jsi = facebook::jsi; 14 | namespace m = margelo; 15 | 16 | namespace rnwgpu { 17 | 18 | struct GPUQuerySetDescriptor { 19 | wgpu::QueryType type; // GPUQueryType 20 | double count; // GPUSize32 21 | std::optional label; // string 22 | }; 23 | 24 | } // namespace rnwgpu 25 | 26 | namespace margelo { 27 | 28 | using namespace rnwgpu; // NOLINT(build/namespaces) 29 | 30 | template <> 31 | struct JSIConverter> { 32 | static std::shared_ptr 33 | fromJSI(jsi::Runtime &runtime, const jsi::Value &arg, bool outOfBounds) { 34 | auto result = std::make_unique(); 35 | if (!outOfBounds && arg.isObject()) { 36 | auto value = arg.getObject(runtime); 37 | if (value.hasProperty(runtime, "type")) { 38 | auto prop = value.getProperty(runtime, "type"); 39 | result->type = 40 | JSIConverter::fromJSI(runtime, prop, false); 41 | } 42 | if (value.hasProperty(runtime, "count")) { 43 | auto prop = value.getProperty(runtime, "count"); 44 | result->count = JSIConverter::fromJSI(runtime, prop, false); 45 | } 46 | if (value.hasProperty(runtime, "label")) { 47 | auto prop = value.getProperty(runtime, "label"); 48 | result->label = JSIConverter>::fromJSI( 49 | runtime, prop, false); 50 | } 51 | } 52 | 53 | return result; 54 | } 55 | static jsi::Value toJSI(jsi::Runtime &runtime, 56 | std::shared_ptr arg) { 57 | throw std::runtime_error("Invalid GPUQuerySetDescriptor::toJSI()"); 58 | } 59 | }; 60 | 61 | } // namespace margelo -------------------------------------------------------------------------------- /packages/webgpu/cpp/rnwgpu/api/descriptors/GPUQueueDescriptor.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | #include 5 | 6 | #include "webgpu/webgpu_cpp.h" 7 | 8 | #include "RNFJSIConverter.h" 9 | #include "WGPULogger.h" 10 | 11 | #include "RNFHybridObject.h" 12 | 13 | namespace jsi = facebook::jsi; 14 | namespace m = margelo; 15 | 16 | namespace rnwgpu { 17 | 18 | struct GPUQueueDescriptor { 19 | std::optional label; // string 20 | }; 21 | 22 | } // namespace rnwgpu 23 | 24 | namespace margelo { 25 | 26 | using namespace rnwgpu; // NOLINT(build/namespaces) 27 | 28 | template <> struct JSIConverter> { 29 | static std::shared_ptr 30 | fromJSI(jsi::Runtime &runtime, const jsi::Value &arg, bool outOfBounds) { 31 | auto result = std::make_unique(); 32 | if (!outOfBounds && arg.isObject()) { 33 | auto value = arg.getObject(runtime); 34 | if (value.hasProperty(runtime, "label")) { 35 | auto prop = value.getProperty(runtime, "label"); 36 | result->label = JSIConverter>::fromJSI( 37 | runtime, prop, false); 38 | } 39 | } 40 | 41 | return result; 42 | } 43 | static jsi::Value toJSI(jsi::Runtime &runtime, 44 | std::shared_ptr arg) { 45 | throw std::runtime_error("Invalid GPUQueueDescriptor::toJSI()"); 46 | } 47 | }; 48 | 49 | } // namespace margelo -------------------------------------------------------------------------------- /packages/webgpu/cpp/rnwgpu/api/descriptors/GPURenderBundleDescriptor.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | #include 5 | 6 | #include "webgpu/webgpu_cpp.h" 7 | 8 | #include "RNFJSIConverter.h" 9 | #include "WGPULogger.h" 10 | 11 | #include "RNFHybridObject.h" 12 | 13 | namespace jsi = facebook::jsi; 14 | namespace m = margelo; 15 | 16 | namespace rnwgpu { 17 | 18 | struct GPURenderBundleDescriptor { 19 | std::optional label; // string 20 | }; 21 | 22 | } // namespace rnwgpu 23 | 24 | namespace margelo { 25 | 26 | using namespace rnwgpu; // NOLINT(build/namespaces) 27 | 28 | template <> 29 | struct JSIConverter> { 30 | static std::shared_ptr 31 | fromJSI(jsi::Runtime &runtime, const jsi::Value &arg, bool outOfBounds) { 32 | auto result = std::make_unique(); 33 | if (!outOfBounds && arg.isObject()) { 34 | auto value = arg.getObject(runtime); 35 | if (value.hasProperty(runtime, "label")) { 36 | auto prop = value.getProperty(runtime, "label"); 37 | result->label = JSIConverter>::fromJSI( 38 | runtime, prop, false); 39 | } 40 | } 41 | 42 | return result; 43 | } 44 | static jsi::Value 45 | toJSI(jsi::Runtime &runtime, 46 | std::shared_ptr arg) { 47 | throw std::runtime_error("Invalid GPURenderBundleDescriptor::toJSI()"); 48 | } 49 | }; 50 | 51 | } // namespace margelo -------------------------------------------------------------------------------- /packages/webgpu/cpp/rnwgpu/api/descriptors/GPURenderPassTimestampWrites.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | 5 | #include "webgpu/webgpu_cpp.h" 6 | 7 | #include "RNFJSIConverter.h" 8 | #include "WGPULogger.h" 9 | 10 | #include "GPUQuerySet.h" 11 | #include "RNFHybridObject.h" 12 | 13 | namespace jsi = facebook::jsi; 14 | namespace m = margelo; 15 | 16 | namespace rnwgpu { 17 | 18 | struct GPURenderPassTimestampWrites { 19 | std::shared_ptr querySet; // GPUQuerySet 20 | std::optional beginningOfPassWriteIndex; // GPUSize32 21 | std::optional endOfPassWriteIndex; // GPUSize32 22 | }; 23 | 24 | } // namespace rnwgpu 25 | 26 | namespace margelo { 27 | 28 | using namespace rnwgpu; // NOLINT(build/namespaces) 29 | 30 | template <> 31 | struct JSIConverter> { 32 | static std::shared_ptr 33 | fromJSI(jsi::Runtime &runtime, const jsi::Value &arg, bool outOfBounds) { 34 | auto result = std::make_unique(); 35 | if (!outOfBounds && arg.isObject()) { 36 | auto value = arg.getObject(runtime); 37 | if (value.hasProperty(runtime, "querySet")) { 38 | auto prop = value.getProperty(runtime, "querySet"); 39 | result->querySet = JSIConverter>::fromJSI( 40 | runtime, prop, false); 41 | } 42 | if (value.hasProperty(runtime, "beginningOfPassWriteIndex")) { 43 | auto prop = value.getProperty(runtime, "beginningOfPassWriteIndex"); 44 | result->beginningOfPassWriteIndex = 45 | JSIConverter>::fromJSI(runtime, prop, false); 46 | } 47 | if (value.hasProperty(runtime, "endOfPassWriteIndex")) { 48 | auto prop = value.getProperty(runtime, "endOfPassWriteIndex"); 49 | result->endOfPassWriteIndex = 50 | JSIConverter>::fromJSI(runtime, prop, false); 51 | } 52 | } 53 | 54 | return result; 55 | } 56 | static jsi::Value 57 | toJSI(jsi::Runtime &runtime, 58 | std::shared_ptr arg) { 59 | throw std::runtime_error("Invalid GPURenderPassTimestampWrites::toJSI()"); 60 | } 61 | }; 62 | 63 | } // namespace margelo -------------------------------------------------------------------------------- /packages/webgpu/cpp/rnwgpu/api/descriptors/GPURequestAdapterOptions.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | 5 | #include "webgpu/webgpu_cpp.h" 6 | 7 | #include "RNFJSIConverter.h" 8 | #include "WGPULogger.h" 9 | 10 | #include "RNFHybridObject.h" 11 | 12 | namespace jsi = facebook::jsi; 13 | namespace m = margelo; 14 | 15 | namespace rnwgpu { 16 | 17 | struct GPURequestAdapterOptions { 18 | std::optional powerPreference; // GPUPowerPreference 19 | std::optional forceFallbackAdapter; // boolean 20 | }; 21 | 22 | } // namespace rnwgpu 23 | 24 | namespace margelo { 25 | 26 | using namespace rnwgpu; // NOLINT(build/namespaces) 27 | 28 | template <> 29 | struct JSIConverter> { 30 | static std::shared_ptr 31 | fromJSI(jsi::Runtime &runtime, const jsi::Value &arg, bool outOfBounds) { 32 | auto result = std::make_unique(); 33 | if (!outOfBounds && arg.isObject()) { 34 | auto value = arg.getObject(runtime); 35 | if (value.hasProperty(runtime, "powerPreference")) { 36 | auto prop = value.getProperty(runtime, "powerPreference"); 37 | result->powerPreference = 38 | JSIConverter>::fromJSI( 39 | runtime, prop, false); 40 | } 41 | if (value.hasProperty(runtime, "forceFallbackAdapter")) { 42 | auto prop = value.getProperty(runtime, "forceFallbackAdapter"); 43 | result->forceFallbackAdapter = 44 | JSIConverter>::fromJSI(runtime, prop, false); 45 | } 46 | } 47 | 48 | return result; 49 | } 50 | static jsi::Value 51 | toJSI(jsi::Runtime &runtime, 52 | std::shared_ptr arg) { 53 | throw std::runtime_error("Invalid GPURequestAdapterOptions::toJSI()"); 54 | } 55 | }; 56 | 57 | } // namespace margelo -------------------------------------------------------------------------------- /packages/webgpu/cpp/rnwgpu/api/descriptors/GPUSamplerBindingLayout.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | 5 | #include "webgpu/webgpu_cpp.h" 6 | 7 | #include "RNFJSIConverter.h" 8 | #include "WGPULogger.h" 9 | 10 | #include "RNFHybridObject.h" 11 | 12 | namespace jsi = facebook::jsi; 13 | namespace m = margelo; 14 | 15 | namespace rnwgpu { 16 | 17 | struct GPUSamplerBindingLayout { 18 | std::optional type; // GPUSamplerBindingType 19 | }; 20 | 21 | } // namespace rnwgpu 22 | 23 | namespace margelo { 24 | 25 | using namespace rnwgpu; // NOLINT(build/namespaces) 26 | 27 | template <> 28 | struct JSIConverter> { 29 | static std::shared_ptr 30 | fromJSI(jsi::Runtime &runtime, const jsi::Value &arg, bool outOfBounds) { 31 | auto result = std::make_unique(); 32 | if (!outOfBounds && arg.isObject()) { 33 | auto value = arg.getObject(runtime); 34 | if (value.hasProperty(runtime, "type")) { 35 | auto prop = value.getProperty(runtime, "type"); 36 | result->type = 37 | JSIConverter>::fromJSI( 38 | runtime, prop, false); 39 | } 40 | } 41 | 42 | return result; 43 | } 44 | static jsi::Value 45 | toJSI(jsi::Runtime &runtime, 46 | std::shared_ptr arg) { 47 | throw std::runtime_error("Invalid GPUSamplerBindingLayout::toJSI()"); 48 | } 49 | }; 50 | 51 | } // namespace margelo -------------------------------------------------------------------------------- /packages/webgpu/cpp/rnwgpu/api/descriptors/GPUShaderModuleCompilationHint.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | #include 5 | 6 | #include "webgpu/webgpu_cpp.h" 7 | 8 | #include "RNFJSIConverter.h" 9 | #include "WGPULogger.h" 10 | 11 | #include "GPUPipelineLayout.h" 12 | #include "RNFHybridObject.h" 13 | 14 | namespace jsi = facebook::jsi; 15 | namespace m = margelo; 16 | 17 | namespace rnwgpu { 18 | 19 | struct GPUShaderModuleCompilationHint { 20 | std::string entryPoint; // string 21 | std::optional< 22 | std::variant>> 23 | layout; // | GPUPipelineLayout | GPUAutoLayoutMode 24 | }; 25 | 26 | } // namespace rnwgpu 27 | 28 | namespace margelo { 29 | 30 | using namespace rnwgpu; // NOLINT(build/namespaces) 31 | 32 | template <> 33 | struct JSIConverter> { 34 | static std::shared_ptr 35 | fromJSI(jsi::Runtime &runtime, const jsi::Value &arg, bool outOfBounds) { 36 | auto result = std::make_unique(); 37 | if (!outOfBounds && arg.isObject()) { 38 | auto value = arg.getObject(runtime); 39 | if (value.hasProperty(runtime, "entryPoint")) { 40 | auto prop = value.getProperty(runtime, "entryPoint"); 41 | result->entryPoint = 42 | JSIConverter::fromJSI(runtime, prop, false); 43 | } 44 | if (value.hasProperty(runtime, "layout")) { 45 | auto prop = value.getProperty(runtime, "layout"); 46 | if (prop.isNull() || prop.isString()) { 47 | result->layout = nullptr; 48 | } else { 49 | result->layout = 50 | JSIConverter>::fromJSI( 51 | runtime, prop, false); 52 | } 53 | } 54 | } 55 | 56 | return result; 57 | } 58 | static jsi::Value 59 | toJSI(jsi::Runtime &runtime, 60 | std::shared_ptr arg) { 61 | throw std::runtime_error("Invalid GPUShaderModuleCompilationHint::toJSI()"); 62 | } 63 | }; 64 | 65 | } // namespace margelo -------------------------------------------------------------------------------- /packages/webgpu/cpp/rnwgpu/api/descriptors/GPUShaderStage.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include 3 | 4 | #include 5 | 6 | #include "webgpu/webgpu_cpp.h" 7 | 8 | namespace rnwgpu { 9 | 10 | namespace m = margelo; 11 | 12 | class GPUShaderStage : public m::HybridObject { 13 | public: 14 | GPUShaderStage() : HybridObject("GPUShaderStage") {} 15 | 16 | public: 17 | double Vertex() { return static_cast(wgpu::ShaderStage::Vertex); } 18 | double Fragment() { return static_cast(wgpu::ShaderStage::Fragment); } 19 | double Compute() { return static_cast(wgpu::ShaderStage::Compute); } 20 | 21 | void loadHybridMethods() override { 22 | registerHybridGetter("VERTEX", &GPUShaderStage::Vertex, this); 23 | registerHybridGetter("FRAGMENT", &GPUShaderStage::Fragment, this); 24 | registerHybridGetter("COMPUTE", &GPUShaderStage::Compute, this); 25 | } 26 | }; 27 | } // namespace rnwgpu -------------------------------------------------------------------------------- /packages/webgpu/cpp/rnwgpu/api/descriptors/GPUTextureBindingLayout.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | 5 | #include "webgpu/webgpu_cpp.h" 6 | 7 | #include "RNFJSIConverter.h" 8 | #include "WGPULogger.h" 9 | 10 | #include "RNFHybridObject.h" 11 | 12 | namespace jsi = facebook::jsi; 13 | namespace m = margelo; 14 | 15 | namespace rnwgpu { 16 | 17 | struct GPUTextureBindingLayout { 18 | std::optional sampleType; // GPUTextureSampleType 19 | std::optional 20 | viewDimension; // GPUTextureViewDimension 21 | std::optional multisampled; // boolean 22 | }; 23 | 24 | } // namespace rnwgpu 25 | 26 | namespace margelo { 27 | 28 | using namespace rnwgpu; // NOLINT(build/namespaces) 29 | 30 | template <> 31 | struct JSIConverter> { 32 | static std::shared_ptr 33 | fromJSI(jsi::Runtime &runtime, const jsi::Value &arg, bool outOfBounds) { 34 | auto result = std::make_unique(); 35 | if (!outOfBounds && arg.isObject()) { 36 | auto value = arg.getObject(runtime); 37 | if (value.hasProperty(runtime, "sampleType")) { 38 | auto prop = value.getProperty(runtime, "sampleType"); 39 | result->sampleType = 40 | JSIConverter>::fromJSI( 41 | runtime, prop, false); 42 | } 43 | if (value.hasProperty(runtime, "viewDimension")) { 44 | auto prop = value.getProperty(runtime, "viewDimension"); 45 | result->viewDimension = 46 | JSIConverter>::fromJSI( 47 | runtime, prop, false); 48 | } 49 | if (value.hasProperty(runtime, "multisampled")) { 50 | auto prop = value.getProperty(runtime, "multisampled"); 51 | result->multisampled = 52 | JSIConverter>::fromJSI(runtime, prop, false); 53 | } 54 | } 55 | 56 | return result; 57 | } 58 | static jsi::Value 59 | toJSI(jsi::Runtime &runtime, 60 | std::shared_ptr arg) { 61 | throw std::runtime_error("Invalid GPUTextureBindingLayout::toJSI()"); 62 | } 63 | }; 64 | 65 | } // namespace margelo -------------------------------------------------------------------------------- /packages/webgpu/cpp/rnwgpu/api/descriptors/GPUTextureUsage.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include 3 | 4 | #include 5 | 6 | #include "webgpu/webgpu_cpp.h" 7 | 8 | namespace rnwgpu { 9 | 10 | namespace m = margelo; 11 | 12 | class GPUTextureUsage : public m::HybridObject { 13 | public: 14 | GPUTextureUsage() : HybridObject("GPUTextureUsage") {} 15 | 16 | public: 17 | double CopySrc() { return static_cast(wgpu::TextureUsage::CopySrc); } 18 | double CopyDst() { return static_cast(wgpu::TextureUsage::CopyDst); } 19 | double TextureBinding() { 20 | return static_cast(wgpu::TextureUsage::TextureBinding); 21 | } 22 | double StorageBinding() { 23 | return static_cast(wgpu::TextureUsage::StorageBinding); 24 | } 25 | double RenderAttachment() { 26 | return static_cast(wgpu::TextureUsage::RenderAttachment); 27 | } 28 | 29 | void loadHybridMethods() override { 30 | registerHybridGetter("COPY_SRC", &GPUTextureUsage::CopySrc, this); 31 | registerHybridGetter("COPY_DST", &GPUTextureUsage::CopyDst, this); 32 | registerHybridGetter("TEXTURE_BINDING", &GPUTextureUsage::TextureBinding, 33 | this); 34 | registerHybridGetter("STORAGE_BINDING", &GPUTextureUsage::StorageBinding, 35 | this); 36 | registerHybridGetter("RENDER_ATTACHMENT", 37 | &GPUTextureUsage::RenderAttachment, this); 38 | } 39 | }; 40 | } // namespace rnwgpu -------------------------------------------------------------------------------- /packages/webgpu/cpp/rnwgpu/api/descriptors/GPUVertexAttribute.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | 5 | #include "webgpu/webgpu_cpp.h" 6 | 7 | #include "RNFJSIConverter.h" 8 | #include "WGPULogger.h" 9 | 10 | #include "RNFHybridObject.h" 11 | 12 | namespace jsi = facebook::jsi; 13 | namespace m = margelo; 14 | 15 | namespace rnwgpu { 16 | 17 | struct GPUVertexAttribute { 18 | wgpu::VertexFormat format; // GPUVertexFormat 19 | double offset; // GPUSize64 20 | double shaderLocation; // GPUIndex32 21 | }; 22 | 23 | } // namespace rnwgpu 24 | 25 | namespace margelo { 26 | 27 | using namespace rnwgpu; // NOLINT(build/namespaces) 28 | 29 | template <> struct JSIConverter> { 30 | static std::shared_ptr 31 | fromJSI(jsi::Runtime &runtime, const jsi::Value &arg, bool outOfBounds) { 32 | auto result = std::make_unique(); 33 | if (!outOfBounds && arg.isObject()) { 34 | auto value = arg.getObject(runtime); 35 | if (value.hasProperty(runtime, "format")) { 36 | auto prop = value.getProperty(runtime, "format"); 37 | result->format = 38 | JSIConverter::fromJSI(runtime, prop, false); 39 | } 40 | if (value.hasProperty(runtime, "offset")) { 41 | auto prop = value.getProperty(runtime, "offset"); 42 | result->offset = JSIConverter::fromJSI(runtime, prop, false); 43 | } 44 | if (value.hasProperty(runtime, "shaderLocation")) { 45 | auto prop = value.getProperty(runtime, "shaderLocation"); 46 | result->shaderLocation = 47 | JSIConverter::fromJSI(runtime, prop, false); 48 | } 49 | } 50 | 51 | return result; 52 | } 53 | static jsi::Value toJSI(jsi::Runtime &runtime, 54 | std::shared_ptr arg) { 55 | throw std::runtime_error("Invalid GPUVertexAttribute::toJSI()"); 56 | } 57 | }; 58 | 59 | } // namespace margelo -------------------------------------------------------------------------------- /packages/webgpu/cpp/threading/CallInvokerDispatcher.h: -------------------------------------------------------------------------------- 1 | 2 | // 3 | // Created by Marc Rousavy on 27.03.24. 4 | // 5 | 6 | #pragma once 7 | 8 | #include "Dispatcher.h" 9 | 10 | #include 11 | #include 12 | #include 13 | 14 | namespace margelo { 15 | 16 | /** 17 | * A Dispatcher that uses react::CallInvoker for it's implementation 18 | */ 19 | class CallInvokerDispatcher final : public Dispatcher { 20 | public: 21 | explicit CallInvokerDispatcher( 22 | std::shared_ptr callInvoker) 23 | : _callInvoker(callInvoker) {} 24 | 25 | void runAsync(std::function &&function) override { 26 | _callInvoker->invokeAsync(std::move(function)); 27 | } 28 | 29 | void runSync(std::function &&function) override { 30 | _callInvoker->invokeSync(std::move(function)); 31 | } 32 | 33 | private: 34 | std::shared_ptr _callInvoker; 35 | }; 36 | 37 | } // namespace margelo 38 | -------------------------------------------------------------------------------- /packages/webgpu/cpp/threading/Dispatcher.cpp: -------------------------------------------------------------------------------- 1 | // 2 | // Created by Marc Rousavy on 12.03.24. 3 | // 4 | 5 | #include "Dispatcher.h" 6 | 7 | #include 8 | #include "RNFJSIHelper.h" 9 | 10 | namespace margelo { 11 | 12 | namespace jsi = facebook::jsi; 13 | 14 | static constexpr auto GLOBAL_DISPATCHER_HOLDER_NAME = "__nitroDispatcher"; 15 | 16 | std::unordered_map> 17 | Dispatcher::_globalCache; 18 | 19 | void Dispatcher::installRuntimeGlobalDispatcher( 20 | jsi::Runtime &runtime, std::shared_ptr dispatcher) { 21 | 22 | // Store a weak reference in global cache 23 | _globalCache[&runtime] = std::weak_ptr(dispatcher); 24 | 25 | // Inject the dispatcher into Runtime global (runtime will hold a strong 26 | // reference) 27 | jsi::Object dispatcherHolder(runtime); 28 | dispatcherHolder.setNativeState(runtime, dispatcher); 29 | runtime.global().setProperty(runtime, GLOBAL_DISPATCHER_HOLDER_NAME, 30 | dispatcherHolder); 31 | } 32 | 33 | std::shared_ptr 34 | Dispatcher::getRuntimeGlobalDispatcher(jsi::Runtime &runtime) { 35 | if (auto search = _globalCache.find(&runtime); search != _globalCache.end()) { 36 | // the runtime is known - we have something in cache 37 | std::weak_ptr weakDispatcher = _globalCache[&runtime]; 38 | std::shared_ptr strongDispatcher = weakDispatcher.lock(); 39 | if (strongDispatcher) { 40 | // the weak reference we cached is still valid - return it! 41 | return strongDispatcher; 42 | } 43 | } 44 | 45 | jsi::Value dispatcherHolderValue = getRuntimeGlobalDispatcherHolder(runtime); 46 | jsi::Object dispatcherHolder = dispatcherHolderValue.getObject(runtime); 47 | return dispatcherHolder.getNativeState(runtime); 48 | } 49 | 50 | jsi::Value Dispatcher::getRuntimeGlobalDispatcherHolder(jsi::Runtime &runtime) { 51 | return runtime.global().getProperty(runtime, GLOBAL_DISPATCHER_HOLDER_NAME); 52 | } 53 | 54 | } // namespace margelo 55 | -------------------------------------------------------------------------------- /packages/webgpu/cpp/threading/ThreadPool.h: -------------------------------------------------------------------------------- 1 | // 2 | // ThreadPool.hpp 3 | // NitroModules 4 | // 5 | // Created by Marc Rousavy on 21.06.24. 6 | // 7 | 8 | #pragma once 9 | 10 | #include 11 | #include 12 | #include 13 | #include 14 | #include 15 | #include 16 | #include 17 | #include 18 | #include 19 | 20 | namespace margelo { 21 | 22 | class ThreadPool final { 23 | public: 24 | /** 25 | * Create a new ThreadPool with the given number of fixed workers/threads. 26 | */ 27 | explicit ThreadPool(const char *const name, size_t numThreads); 28 | ~ThreadPool(); 29 | 30 | /** 31 | * Schedules the given task asynchronously on the ThreadPool. 32 | * It will run once a worker is available. 33 | */ 34 | void run(std::function &&task); 35 | 36 | public: 37 | /** 38 | * Get a static singleton instance - a shared ThreadPool. 39 | * The shared ThreadPool has 3 threads. 40 | */ 41 | static std::shared_ptr getSharedPool(); 42 | 43 | private: 44 | std::vector _workers; 45 | std::queue> _tasks; 46 | std::mutex _queueMutex; 47 | std::condition_variable _condition; 48 | std::atomic _isAlive; 49 | const char *_name; 50 | static constexpr auto TAG = "ThreadPool"; 51 | }; 52 | 53 | } // namespace margelo 54 | -------------------------------------------------------------------------------- /packages/webgpu/jest.config.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | preset: 'react-native', 3 | modulePathIgnorePatterns: [ 4 | '(meshes)|(setup)|(setup.(ts|tsx))', 5 | 'components', 6 | 'config.ts', 7 | 'globalSetup.ts', 8 | 'globalTeardown.ts' 9 | ], 10 | globalSetup: './src/__tests__/globalSetup.ts', 11 | globalTeardown: './src/__tests__/globalTeardown.ts', 12 | transform: { 13 | '^.+\\.(js|jsx|ts|tsx)$': 'babel-jest', 14 | }, 15 | transformIgnorePatterns: [ 16 | 'node_modules/(?!(wgpu-matrix|react-native|@react-native|react-native-.*)/)', 17 | ], 18 | }; -------------------------------------------------------------------------------- /packages/webgpu/react-native-wgpu.podspec: -------------------------------------------------------------------------------- 1 | require "json" 2 | 3 | package = JSON.parse(File.read(File.join(__dir__, "package.json"))) 4 | folly_compiler_flags = '-DFOLLY_NO_CONFIG -DFOLLY_MOBILE=1 -DFOLLY_USE_LIBCPP=1 -Wno-comma -Wno-shorten-64-to-32' 5 | 6 | Pod::Spec.new do |s| 7 | s.name = "react-native-wgpu" 8 | s.version = package["version"] 9 | s.summary = package["description"] 10 | s.homepage = package["homepage"] 11 | s.license = package["license"] 12 | s.authors = package["author"] 13 | 14 | s.platforms = { :ios => min_ios_version_supported, :osx => "10.15", :visionos => "1.0" } 15 | s.source = { :git => "https://github.com/wcandillon/react-native-webgpu.git", :tag => "#{s.version}" } 16 | 17 | s.source_files = [ 18 | "apple/**/*.{h,c,cc,cpp,m,mm,swift}", 19 | "cpp/**/*.{h,cpp}" 20 | ] 21 | 22 | s.vendored_frameworks = 'libs/apple/libwebgpu_dawn.xcframework' 23 | 24 | s.pod_target_xcconfig = { 25 | 'HEADER_SEARCH_PATHS' => '$(PODS_TARGET_SRCROOT)/cpp', 26 | } 27 | 28 | # Use install_modules_dependencies helper to install the dependencies if React Native version >=0.71.0. 29 | # See https://github.com/facebook/react-native/blob/febf6b7f33fdb4904669f99d795eba4c0f95d7bf/scripts/cocoapods/new_architecture.rb#L79. 30 | if respond_to?(:install_modules_dependencies, true) 31 | install_modules_dependencies(s) 32 | else 33 | s.dependency "React-Core" 34 | 35 | # Don't install the dependencies when we run `pod install` in the old architecture. 36 | if ENV['RCT_NEW_ARCH_ENABLED'] == '1' then 37 | s.compiler_flags = folly_compiler_flags + " -DRCT_NEW_ARCH_ENABLED=1" 38 | s.pod_target_xcconfig = { 39 | "HEADER_SEARCH_PATHS" => "\"$(PODS_ROOT)/boost\"", 40 | "OTHER_CPLUSPLUSFLAGS" => "-DFOLLY_NO_CONFIG -DFOLLY_MOBILE=1 -DFOLLY_USE_LIBCPP=1", 41 | "CLANG_CXX_LANGUAGE_STANDARD" => "c++17" 42 | } 43 | s.dependency "React-RCTFabric" 44 | s.dependency "React-Codegen" 45 | s.dependency "RCT-Folly" 46 | s.dependency "RCTRequired" 47 | s.dependency "RCTTypeSafety" 48 | s.dependency "ReactCommon/turbomodule/core" 49 | end 50 | end 51 | end 52 | -------------------------------------------------------------------------------- /packages/webgpu/scripts/build/copy-artifacts.ts: -------------------------------------------------------------------------------- 1 | import { checkBuildArtifacts } from "./dawn-configuration"; 2 | import { $ } from "./util"; 3 | 4 | $("cp -R ../../artifacts/libs ."); 5 | $("cp -R ../../artifacts/cpp/webgpu cpp"); 6 | $("cp -R ../../artifacts/cpp/dawn cpp"); 7 | checkBuildArtifacts(); 8 | -------------------------------------------------------------------------------- /packages/webgpu/scripts/build/download-artifacts.ts: -------------------------------------------------------------------------------- 1 | /* eslint-disable max-len */ 2 | import fs from "fs"; 3 | import path from "path"; 4 | 5 | import { $ } from "./util"; 6 | 7 | const repo = "wcandillon/react-native-webgpu"; 8 | const workflow = "build-dawn.yml"; 9 | const artifactName = "dawn-libs"; 10 | //const branch = "main"; 11 | 12 | const artifactsDir = path.resolve(__dirname, "../../../../artifacts"); 13 | 14 | // Function to clear directory contents 15 | const clearDirectory = (directory: string) => { 16 | if (fs.existsSync(directory)) { 17 | fs.readdirSync(directory).forEach((file) => { 18 | const curPath = path.join(directory, file); 19 | if (fs.lstatSync(curPath).isDirectory()) { 20 | clearDirectory(curPath); 21 | fs.rmdirSync(curPath); 22 | } else { 23 | fs.unlinkSync(curPath); 24 | } 25 | }); 26 | console.log(`❌ ${directory}`); 27 | } else { 28 | console.log(`Directory ${directory} does not exist, creating it...`); 29 | fs.mkdirSync(directory, { recursive: true }); 30 | } 31 | }; 32 | 33 | const result = $( 34 | `gh run list --repo "${repo}" --workflow "${workflow}" --status success --limit 1 --json databaseId --jq '.[0].databaseId'`, 35 | ); 36 | const id = result.toString("utf8").trim(); 37 | 38 | console.log("Clearing existing artifacts..."); 39 | clearDirectory(artifactsDir); 40 | 41 | console.log(`Downloading artifacts to ${artifactsDir}`); 42 | $( 43 | `gh run download "${id}" --repo "${repo}" --name "${artifactName}" --dir ${artifactsDir}`, 44 | ); 45 | console.log("Done"); 46 | -------------------------------------------------------------------------------- /packages/webgpu/scripts/build/util.ts: -------------------------------------------------------------------------------- 1 | import { spawn, execSync } from "child_process"; 2 | import { existsSync } from "fs"; 3 | import { exit } from "process"; 4 | 5 | export const runAsync = (command: string, label: string): Promise => { 6 | return new Promise((resolve, reject) => { 7 | const [cmd, ...args] = command.split(" "); 8 | console.log({ cmd, args }); 9 | const childProcess = spawn(cmd, args, { 10 | shell: true, 11 | }); 12 | 13 | childProcess.stdout.on("data", (data) => { 14 | process.stdout.write(`${label} ${data}`); 15 | }); 16 | 17 | childProcess.stderr.on("data", (data) => { 18 | console.error(`${label} ${data}`); 19 | }); 20 | 21 | childProcess.on("close", (code) => { 22 | if (code === 0) { 23 | resolve(); 24 | } else { 25 | reject(new Error(`${label} exited with code ${code}`)); 26 | } 27 | }); 28 | 29 | childProcess.on("error", (error) => { 30 | reject(new Error(`${label} ${error.message}`)); 31 | }); 32 | }); 33 | }; 34 | 35 | export const mapKeys = (obj: T) => 36 | Object.keys(obj) as (keyof T)[]; 37 | 38 | export const checkFileExists = (filePath: string) => { 39 | const exists = existsSync(filePath); 40 | if (!exists) { 41 | console.log(""); 42 | console.log("Failed:"); 43 | console.log(filePath + " not found. (" + filePath + ")"); 44 | console.log(""); 45 | exit(1); 46 | } else { 47 | console.log("✅ " + filePath); 48 | } 49 | }; 50 | 51 | export const $ = (command: string) => { 52 | try { 53 | return execSync(command); 54 | } catch (e) { 55 | exit(1); 56 | } 57 | }; 58 | -------------------------------------------------------------------------------- /packages/webgpu/scripts/codegen/templates/Enum.ts: -------------------------------------------------------------------------------- 1 | import _ from "lodash"; 2 | import type { PropertySignature, VariableDeclaration } from "ts-morph"; 3 | import { Node } from "ts-morph"; 4 | 5 | const enumAliases: Record = { 6 | ColorWrite: "ColorWriteMask", 7 | }; 8 | 9 | const getPropName = (prop: PropertySignature) => { 10 | const name = _.upperFirst(_.camelCase(prop.getName())); 11 | return name; 12 | }; 13 | 14 | export const getEnum = (decl: VariableDeclaration) => { 15 | const name = decl.getName(); 16 | const wname = enumAliases[name.substring(3)] || name.substring(3); 17 | const properties = decl.getDescendants().filter(Node.isPropertySignature); 18 | return `#pragma once 19 | #include 20 | 21 | #include 22 | 23 | #include "webgpu/webgpu_cpp.h" 24 | 25 | namespace rnwgpu { 26 | 27 | namespace m = margelo; 28 | 29 | class ${name} : public m::HybridObject { 30 | public: 31 | ${name}() : HybridObject("${name}") {} 32 | 33 | public: 34 | ${properties 35 | .map((property) => { 36 | const prop = getPropName(property); 37 | return `double ${prop}() { 38 | return static_cast(wgpu::${wname}::${prop}); 39 | }`; 40 | }) 41 | .join("\n ")} 42 | 43 | void loadHybridMethods() override { 44 | ${properties 45 | .map((property) => { 46 | const prop = getPropName(property); 47 | return `registerHybridGetter("${property.getName()}", &${name}::${prop}, this);`; 48 | }) 49 | .join("\n ")} 50 | } 51 | }; 52 | } // namespace rnwgpu`; 53 | }; 54 | -------------------------------------------------------------------------------- /packages/webgpu/scripts/codegen/util.ts: -------------------------------------------------------------------------------- 1 | import { execSync } from "child_process"; 2 | import { writeFileSync } from "fs"; 3 | import path from "path"; 4 | import { exit } from "process"; 5 | 6 | const $ = (command: string) => { 7 | try { 8 | return execSync(command); 9 | } catch (e) { 10 | exit(1); 11 | } 12 | }; 13 | 14 | const labels = { 15 | object: "🧩", // Puzzle piece to represent an object 16 | descriptor: "📝", // Memo to represent a descriptor 17 | enum: "🔢", // Input numbers to represent an enumeration 18 | union: "🔗", // Link symbol to represent a union of types 19 | errors: "🚨", // Warning sign to represent errors 20 | }; 21 | 22 | export const writeFile = ( 23 | label: keyof typeof labels, 24 | name: string, 25 | content: string, 26 | ) => { 27 | const descriptors = label === "object" ? false : true; 28 | const file = path.resolve( 29 | __dirname, 30 | `../../cpp/rnwgpu/api/${descriptors ? "descriptors" : ""}/${name}.h`, 31 | ); 32 | $(`touch ${file}`); 33 | writeFileSync(file, content, "utf8"); 34 | console.log( 35 | `${labels[label]} ${file.substring(file.indexOf("/package/") + "/package/".length)}`, 36 | ); 37 | }; 38 | -------------------------------------------------------------------------------- /packages/webgpu/src/NativeWebGPUModule.ts: -------------------------------------------------------------------------------- 1 | import type { TurboModule } from "react-native/Libraries/TurboModule/RCTExport"; 2 | import { TurboModuleRegistry } from "react-native"; 3 | 4 | export interface Spec extends TurboModule { 5 | install: () => boolean; 6 | } 7 | 8 | // eslint-disable-next-line import/no-default-export 9 | export default TurboModuleRegistry.getEnforcing("WebGPUModule"); 10 | -------------------------------------------------------------------------------- /packages/webgpu/src/WebGPUView.tsx: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wcandillon/react-native-webgpu/a6dbc83a14784a37a1d3b7ce57b839c70b479d2f/packages/webgpu/src/WebGPUView.tsx -------------------------------------------------------------------------------- /packages/webgpu/src/WebGPUViewNativeComponent.ts: -------------------------------------------------------------------------------- 1 | import codegenNativeComponent from "react-native/Libraries/Utilities/codegenNativeComponent"; 2 | import type { ViewProps } from "react-native"; 3 | import type { Int32 } from "react-native/Libraries/Types/CodegenTypes"; 4 | 5 | interface NativeProps extends ViewProps { 6 | contextId: Int32; 7 | transparent: boolean; 8 | } 9 | 10 | // eslint-disable-next-line import/no-default-export 11 | export default codegenNativeComponent("WebGPUView"); 12 | -------------------------------------------------------------------------------- /packages/webgpu/src/__tests__/Alpha.spec.ts: -------------------------------------------------------------------------------- 1 | import { checkImage, client, encodeImage } from "./setup"; 2 | 3 | describe("Alpha", () => { 4 | it("Premultiplied Color", async () => { 5 | const result = await client.eval(({ device, ctx, canvas }) => { 6 | const commandEncoder = device.createCommandEncoder(); 7 | const textureView = ctx.getCurrentTexture().createView(); 8 | const alpha = 0.5; 9 | const renderPassDescriptor: GPURenderPassDescriptor = { 10 | colorAttachments: [ 11 | { 12 | view: textureView, 13 | clearValue: [0.3 * alpha, 0.6 * alpha, 1 * alpha, alpha], 14 | loadOp: "clear", 15 | storeOp: "store", 16 | }, 17 | ], 18 | }; 19 | 20 | const passEncoder = commandEncoder.beginRenderPass(renderPassDescriptor); 21 | passEncoder.end(); 22 | device.queue.submit([commandEncoder.finish()]); 23 | return canvas.getImageData(); 24 | }); 25 | const image = encodeImage(result); 26 | checkImage(image, "snapshots/semi-opaque-cyan.png"); 27 | }); 28 | }); 29 | -------------------------------------------------------------------------------- /packages/webgpu/src/__tests__/Device.spec.ts: -------------------------------------------------------------------------------- 1 | import { client } from "./setup"; 2 | 3 | describe("Device", () => { 4 | it("request device (1)", async () => { 5 | const result = await client.eval(({ adapter }) => 6 | adapter.requestDevice().then((device) => device !== null), 7 | ); 8 | expect(result).toBe(true); 9 | }); 10 | 11 | it("request device (2)", async () => { 12 | const result = await client.eval(({ adapter }) => 13 | adapter.requestDevice(undefined).then((device) => device.label), 14 | ); 15 | expect(result).toBe(""); 16 | }); 17 | it("request device (3)", async () => { 18 | const result = await client.eval(({ adapter }) => 19 | adapter.requestDevice({ label: "MyGPU" }).then((device) => device.label), 20 | ); 21 | expect(result).toBe("MyGPU"); 22 | }); 23 | it("destroy device (3)", async () => { 24 | const result = await client.eval(({ adapter }) => 25 | adapter.requestDevice({ label: "MyGPU" }).then((device) => { 26 | device.destroy(); 27 | return device.lost.then((r) => ({ 28 | reason: r.reason, 29 | message: r.message, 30 | })); 31 | }), 32 | ); 33 | expect(["unknown", "destroyed"].includes(result.reason)).toBe(true); 34 | }); 35 | 36 | it("times out device.lost if the device has not been destroyed", async () => { 37 | const isDeviceLost = await client.eval(({ device }) => { 38 | const timeout = new Promise((resolve) => { 39 | setTimeout(() => { 40 | resolve(false); 41 | }, 50); 42 | }); 43 | 44 | return Promise.race([device.lost.then(() => true), timeout]); 45 | }); 46 | 47 | expect(isDeviceLost).toBeFalsy(); 48 | }); 49 | 50 | it("resolves an awaited device.lost when device.destroy is called", async () => { 51 | const result = await client.eval(({ adapter }) => 52 | adapter.requestDevice({ label: "myGPU2" }).then((device) => { 53 | setTimeout(() => { 54 | device.destroy(); 55 | }, 50); 56 | 57 | return device.lost.then((r) => ({ 58 | reason: r.reason, 59 | message: r.message, 60 | })); 61 | }), 62 | ); 63 | 64 | expect(["unknown", "destroyed"].includes(result.reason)).toBeTruthy(); 65 | }); 66 | }); 67 | -------------------------------------------------------------------------------- /packages/webgpu/src/__tests__/ImageData.spec.ts: -------------------------------------------------------------------------------- 1 | import path from "path"; 2 | 3 | import { checkImage, client, encodeImage, decodeImage } from "./setup"; 4 | 5 | describe("Image Bitmap", () => { 6 | it("createImageBitmap (1)", async () => { 7 | const bitmap = await decodeImage( 8 | path.join(__dirname, "./assets/Di-3d.png"), 9 | ); 10 | const image = encodeImage(bitmap); 11 | checkImage(image, "snapshots/ref.png"); 12 | }); 13 | it("createImageBitmap (2)", async () => { 14 | const bitmap = await decodeImage( 15 | path.join(__dirname, "./assets/Di-3d.png"), 16 | ); 17 | const result = await client.eval( 18 | ({ bitmap: bmp }) => { 19 | return bmp; 20 | }, 21 | { bitmap }, 22 | ); 23 | const image = encodeImage(result); 24 | checkImage(image, "snapshots/ref.png"); 25 | }); 26 | }); 27 | -------------------------------------------------------------------------------- /packages/webgpu/src/__tests__/assets/Di-3d.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wcandillon/react-native-webgpu/a6dbc83a14784a37a1d3b7ce57b839c70b479d2f/packages/webgpu/src/__tests__/assets/Di-3d.png -------------------------------------------------------------------------------- /packages/webgpu/src/__tests__/components/Wireframe/utils.ts: -------------------------------------------------------------------------------- 1 | export function rand(min?: number, max?: number) { 2 | if (min === undefined) { 3 | max = 1; 4 | min = 0; 5 | } else if (max === undefined) { 6 | max = min; 7 | min = 0; 8 | } 9 | return Math.random() * (max - min) + min; 10 | } 11 | 12 | export function randInt(min: number, max?: number) { 13 | return Math.floor(rand(min, max)); 14 | } 15 | 16 | export function randColor() { 17 | return [rand(), rand(), rand(), 1]; 18 | } 19 | 20 | export function randElement(arr: T[]): T { 21 | return arr[randInt(arr.length)]; 22 | } 23 | -------------------------------------------------------------------------------- /packages/webgpu/src/__tests__/components/cube.ts: -------------------------------------------------------------------------------- 1 | export const cubeVertexSize = 4 * 10; // Byte size of one cube vertex. 2 | export const cubePositionOffset = 0; 3 | export const cubeColorOffset = 4 * 4; // Byte offset of cube vertex color attribute. 4 | export const cubeUVOffset = 4 * 8; 5 | export const cubeVertexCount = 36; 6 | 7 | // prettier-ignore 8 | export const cubeVertexArray = new Float32Array([ 9 | // float4 position, float4 color, float2 uv, 10 | 1, -1, 1, 1, 1, 0, 1, 1, 0, 1, 11 | -1, -1, 1, 1, 0, 0, 1, 1, 1, 1, 12 | -1, -1, -1, 1, 0, 0, 0, 1, 1, 0, 13 | 1, -1, -1, 1, 1, 0, 0, 1, 0, 0, 14 | 1, -1, 1, 1, 1, 0, 1, 1, 0, 1, 15 | -1, -1, -1, 1, 0, 0, 0, 1, 1, 0, 16 | 17 | 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 18 | 1, -1, 1, 1, 1, 0, 1, 1, 1, 1, 19 | 1, -1, -1, 1, 1, 0, 0, 1, 1, 0, 20 | 1, 1, -1, 1, 1, 1, 0, 1, 0, 0, 21 | 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 22 | 1, -1, -1, 1, 1, 0, 0, 1, 1, 0, 23 | 24 | -1, 1, 1, 1, 0, 1, 1, 1, 0, 1, 25 | 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 26 | 1, 1, -1, 1, 1, 1, 0, 1, 1, 0, 27 | -1, 1, -1, 1, 0, 1, 0, 1, 0, 0, 28 | -1, 1, 1, 1, 0, 1, 1, 1, 0, 1, 29 | 1, 1, -1, 1, 1, 1, 0, 1, 1, 0, 30 | 31 | -1, -1, 1, 1, 0, 0, 1, 1, 0, 1, 32 | -1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 33 | -1, 1, -1, 1, 0, 1, 0, 1, 1, 0, 34 | -1, -1, -1, 1, 0, 0, 0, 1, 0, 0, 35 | -1, -1, 1, 1, 0, 0, 1, 1, 0, 1, 36 | -1, 1, -1, 1, 0, 1, 0, 1, 1, 0, 37 | 38 | 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 39 | -1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 40 | -1, -1, 1, 1, 0, 0, 1, 1, 1, 0, 41 | -1, -1, 1, 1, 0, 0, 1, 1, 1, 0, 42 | 1, -1, 1, 1, 1, 0, 1, 1, 0, 0, 43 | 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 44 | 45 | 1, -1, -1, 1, 1, 0, 0, 1, 0, 1, 46 | -1, -1, -1, 1, 0, 0, 0, 1, 1, 1, 47 | -1, 1, -1, 1, 0, 1, 0, 1, 1, 0, 48 | 1, 1, -1, 1, 1, 1, 0, 1, 0, 0, 49 | 1, -1, -1, 1, 1, 0, 0, 1, 0, 1, 50 | -1, 1, -1, 1, 0, 1, 0, 1, 1, 0, 51 | ]); 52 | -------------------------------------------------------------------------------- /packages/webgpu/src/__tests__/components/meshes/stanfordDragon.ts: -------------------------------------------------------------------------------- 1 | import dragonRawData from './stanfordDragonData'; 2 | import { computeProjectedPlaneUVs, generateNormals } from './utils'; 3 | 4 | const { positions, normals, triangles } = generateNormals( 5 | Math.PI, 6 | dragonRawData.positions as [number, number, number][], 7 | dragonRawData.cells as [number, number, number][] 8 | ); 9 | 10 | const uvs = computeProjectedPlaneUVs(positions, 'xy'); 11 | 12 | // Push indices for an additional ground plane 13 | triangles.push( 14 | [positions.length, positions.length + 2, positions.length + 1], 15 | [positions.length, positions.length + 1, positions.length + 3] 16 | ); 17 | 18 | // Push vertex attributes for an additional ground plane 19 | // prettier-ignore 20 | positions.push( 21 | [-100, 20, -100], // 22 | [ 100, 20, 100], // 23 | [-100, 20, 100], // 24 | [ 100, 20, -100] 25 | ); 26 | normals.push( 27 | [0, 1, 0], // 28 | [0, 1, 0], // 29 | [0, 1, 0], // 30 | [0, 1, 0] 31 | ); 32 | uvs.push( 33 | [0, 0], // 34 | [1, 1], // 35 | [0, 1], // 36 | [1, 0] 37 | ); 38 | 39 | export const mesh = { 40 | positions, 41 | triangles, 42 | normals, 43 | uvs, 44 | }; 45 | -------------------------------------------------------------------------------- /packages/webgpu/src/__tests__/components/meshes/teapot.ts: -------------------------------------------------------------------------------- 1 | // @ts-expect-error 2 | import teapotData from "teapot"; 3 | 4 | import { computeSurfaceNormals } from "./utils"; 5 | 6 | export const mesh = { 7 | positions: teapotData.positions as [number, number, number][], 8 | triangles: teapotData.cells as [number, number, number][], 9 | normals: [] as [number, number, number][], 10 | }; 11 | 12 | // Compute surface normals 13 | mesh.normals = computeSurfaceNormals(mesh.positions, mesh.triangles); 14 | -------------------------------------------------------------------------------- /packages/webgpu/src/__tests__/components/triangle.ts: -------------------------------------------------------------------------------- 1 | export const triangleVertWGSL = `@vertex 2 | fn main( 3 | @builtin(vertex_index) VertexIndex : u32 4 | ) -> @builtin(position) vec4f { 5 | var pos = array( 6 | vec2(0.0, 0.5), 7 | vec2(-0.5, -0.5), 8 | vec2(0.5, -0.5) 9 | ); 10 | 11 | return vec4f(pos[VertexIndex], 0.0, 1.0); 12 | }`; 13 | 14 | export const redFragWGSL = `@fragment 15 | fn main() -> @location(0) vec4f { 16 | return vec4(1.0, 0.0, 0.0, 1.0); 17 | }`; 18 | -------------------------------------------------------------------------------- /packages/webgpu/src/__tests__/config.ts: -------------------------------------------------------------------------------- 1 | export const DEBUG = process.env.DEBUG === "true"; 2 | export const REFERENCE = process.env.REFERENCE === "true"; 3 | -------------------------------------------------------------------------------- /packages/webgpu/src/__tests__/globalSetup.ts: -------------------------------------------------------------------------------- 1 | /* eslint-disable no-var */ 2 | import type { Server, WebSocket } from "ws"; 3 | import { WebSocketServer } from "ws"; 4 | 5 | import { REFERENCE } from "./config"; 6 | 7 | declare global { 8 | var testServer: Server; 9 | var testClient: WebSocket; 10 | var testOS: "ios" | "android" | "web" | "node"; 11 | var testArch: "paper" | "fabric"; 12 | } 13 | 14 | const isOS = (os: string): os is "android" | "ios" | "web" => { 15 | return ["ios", "android", "web"].indexOf(os) !== -1; 16 | }; 17 | 18 | const isArch = (arc: string): arc is "paper" | "fabric" => { 19 | return ["paper", "fabric"].indexOf(arc) !== -1; 20 | }; 21 | 22 | const globalSetup = () => { 23 | return new Promise((resolve) => { 24 | if (REFERENCE) { 25 | resolve(); 26 | return; 27 | } 28 | const port = 4242; 29 | global.testServer = new WebSocketServer({ port }); 30 | console.log( 31 | `\n\nTest server listening on port ${port} (waiting for the example app to open on E2E tests screen)`, 32 | ); 33 | global.testServer.on("connection", (client) => { 34 | global.testClient = client; 35 | client.once("message", (msg) => { 36 | const obj = JSON.parse(msg.toString("utf8")); 37 | const { OS, arch } = obj; 38 | if (!isOS(OS)) { 39 | throw new Error("Unknown testing platform: " + OS); 40 | } 41 | if (!isArch(arch)) { 42 | throw new Error("Unknown testing architecture: " + arch); 43 | } 44 | global.testOS = OS; 45 | global.testArch = arch; 46 | console.log(`${OS} device connected (${arch})`); 47 | resolve(); 48 | }); 49 | }); 50 | }); 51 | }; 52 | 53 | // eslint-disable-next-line import/no-default-export 54 | export default globalSetup; 55 | -------------------------------------------------------------------------------- /packages/webgpu/src/__tests__/globalTeardown.ts: -------------------------------------------------------------------------------- 1 | const globalTeardown = () => { 2 | if (global.testClient) { 3 | global.testClient.close(); 4 | } 5 | if (global.testServer) { 6 | global.testServer.close(); 7 | } 8 | }; 9 | 10 | // eslint-disable-next-line import/no-default-export 11 | export default globalTeardown; 12 | -------------------------------------------------------------------------------- /packages/webgpu/src/__tests__/snapshots/abuffer.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wcandillon/react-native-webgpu/a6dbc83a14784a37a1d3b7ce57b839c70b479d2f/packages/webgpu/src/__tests__/snapshots/abuffer.png -------------------------------------------------------------------------------- /packages/webgpu/src/__tests__/snapshots/asteroid.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wcandillon/react-native-webgpu/a6dbc83a14784a37a1d3b7ce57b839c70b479d2f/packages/webgpu/src/__tests__/snapshots/asteroid.png -------------------------------------------------------------------------------- /packages/webgpu/src/__tests__/snapshots/blur.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wcandillon/react-native-webgpu/a6dbc83a14784a37a1d3b7ce57b839c70b479d2f/packages/webgpu/src/__tests__/snapshots/blur.png -------------------------------------------------------------------------------- /packages/webgpu/src/__tests__/snapshots/buffer.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wcandillon/react-native-webgpu/a6dbc83a14784a37a1d3b7ce57b839c70b479d2f/packages/webgpu/src/__tests__/snapshots/buffer.png -------------------------------------------------------------------------------- /packages/webgpu/src/__tests__/snapshots/constant-triangle.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wcandillon/react-native-webgpu/a6dbc83a14784a37a1d3b7ce57b839c70b479d2f/packages/webgpu/src/__tests__/snapshots/constant-triangle.png -------------------------------------------------------------------------------- /packages/webgpu/src/__tests__/snapshots/cube.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wcandillon/react-native-webgpu/a6dbc83a14784a37a1d3b7ce57b839c70b479d2f/packages/webgpu/src/__tests__/snapshots/cube.png -------------------------------------------------------------------------------- /packages/webgpu/src/__tests__/snapshots/f.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wcandillon/react-native-webgpu/a6dbc83a14784a37a1d3b7ce57b839c70b479d2f/packages/webgpu/src/__tests__/snapshots/f.png -------------------------------------------------------------------------------- /packages/webgpu/src/__tests__/snapshots/f2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wcandillon/react-native-webgpu/a6dbc83a14784a37a1d3b7ce57b839c70b479d2f/packages/webgpu/src/__tests__/snapshots/f2.png -------------------------------------------------------------------------------- /packages/webgpu/src/__tests__/snapshots/fractal-cubes.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wcandillon/react-native-webgpu/a6dbc83a14784a37a1d3b7ce57b839c70b479d2f/packages/webgpu/src/__tests__/snapshots/fractal-cubes.png -------------------------------------------------------------------------------- /packages/webgpu/src/__tests__/snapshots/instanced-cubes.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wcandillon/react-native-webgpu/a6dbc83a14784a37a1d3b7ce57b839c70b479d2f/packages/webgpu/src/__tests__/snapshots/instanced-cubes.png -------------------------------------------------------------------------------- /packages/webgpu/src/__tests__/snapshots/occlusion-query.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wcandillon/react-native-webgpu/a6dbc83a14784a37a1d3b7ce57b839c70b479d2f/packages/webgpu/src/__tests__/snapshots/occlusion-query.png -------------------------------------------------------------------------------- /packages/webgpu/src/__tests__/snapshots/ref.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wcandillon/react-native-webgpu/a6dbc83a14784a37a1d3b7ce57b839c70b479d2f/packages/webgpu/src/__tests__/snapshots/ref.png -------------------------------------------------------------------------------- /packages/webgpu/src/__tests__/snapshots/semi-opaque-cyan.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wcandillon/react-native-webgpu/a6dbc83a14784a37a1d3b7ce57b839c70b479d2f/packages/webgpu/src/__tests__/snapshots/semi-opaque-cyan.png -------------------------------------------------------------------------------- /packages/webgpu/src/__tests__/snapshots/texture.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wcandillon/react-native-webgpu/a6dbc83a14784a37a1d3b7ce57b839c70b479d2f/packages/webgpu/src/__tests__/snapshots/texture.png -------------------------------------------------------------------------------- /packages/webgpu/src/__tests__/snapshots/textured-cube.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wcandillon/react-native-webgpu/a6dbc83a14784a37a1d3b7ce57b839c70b479d2f/packages/webgpu/src/__tests__/snapshots/textured-cube.png -------------------------------------------------------------------------------- /packages/webgpu/src/__tests__/snapshots/triangle-msaa.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wcandillon/react-native-webgpu/a6dbc83a14784a37a1d3b7ce57b839c70b479d2f/packages/webgpu/src/__tests__/snapshots/triangle-msaa.png -------------------------------------------------------------------------------- /packages/webgpu/src/__tests__/snapshots/triangle.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wcandillon/react-native-webgpu/a6dbc83a14784a37a1d3b7ce57b839c70b479d2f/packages/webgpu/src/__tests__/snapshots/triangle.png -------------------------------------------------------------------------------- /packages/webgpu/src/__tests__/snapshots/two-cube.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wcandillon/react-native-webgpu/a6dbc83a14784a37a1d3b7ce57b839c70b479d2f/packages/webgpu/src/__tests__/snapshots/two-cube.png -------------------------------------------------------------------------------- /packages/webgpu/tsconfig.build.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "./tsconfig", 3 | "exclude": ["scripts"], 4 | "compilerOptions": { 5 | "noEmit": false, 6 | } 7 | } 8 | -------------------------------------------------------------------------------- /packages/webgpu/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "eslint-config-react-native-wcandillon/tsconfig.base", 3 | "compilerOptions": { 4 | "noUncheckedIndexedAccess": false, 5 | "types": ["@webgpu/types", "@types/node", "@types/jest"] 6 | } 7 | } 8 | -------------------------------------------------------------------------------- /turbo.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "https://turbo.build/schema.json", 3 | "tasks": { 4 | "build:android": { 5 | "env": ["JAVA_HOME", "ANDROID_NDK", "ANDROID_SDK", "ANDROID_HOME"], 6 | "outputs": [ 7 | "apps/*/android", 8 | "!apps/*/android/.gradle", 9 | "!apps/*/android/build", 10 | "!apps/*/android/app/build" 11 | ], 12 | "inputs": [ 13 | "**/package.json", 14 | "packages/webgpu/android", 15 | "!packages/webgpu/android/build", 16 | "packages/webgpu/cpp/**", 17 | "apps/*/android/**", 18 | "apps/*/android/app/build.gradle", 19 | "apps/*/android/build.gradle", 20 | "apps/*/android/gradle.properties", 21 | "apps/*/android/local.properties", 22 | "!apps/*/android/.gradle", 23 | "!apps/*/android/build", 24 | "!apps/*/android/app/build" 25 | ] 26 | }, 27 | "build:ios": { 28 | "dependsOn": ["pod:install:ios"], 29 | "outputs": [ 30 | "apps/*/ios/build", 31 | "apps/*/ios/Pods" 32 | ], 33 | "inputs": [ 34 | "**/package.json", 35 | "**/*.podspec", 36 | "packages/webgpu/cpp/**", 37 | "packages/webgpu/apple/**", 38 | "apps/*/package.json", 39 | "apps/*/ios", 40 | "!apps/*/ios/build", 41 | "!apps/*/ios/Pods" 42 | ] 43 | }, 44 | "build:macos": { 45 | "dependsOn": ["pod:install:macos"], 46 | "outputs": [ 47 | "apps/*/macos/build", 48 | "apps/*/macos/Pods" 49 | ], 50 | "inputs": [ 51 | "**/package.json", 52 | "**/*.podspec", 53 | "packages/webgpu/cpp/**", 54 | "packages/webgpu/apple/**", 55 | "apps/*/package.json", 56 | "apps/*/macos", 57 | "!apps/*/macos/build", 58 | "!apps/*/macos/Pods" 59 | ] 60 | }, 61 | "pod:install:ios": { 62 | "cache": false, 63 | "inputs": ["**/ios/Podfile", "**/ios/Podfile.lock"], 64 | "outputs": ["**/ios/Pods/**"] 65 | }, 66 | "pod:install:macos": { 67 | "cache": false, 68 | "inputs": ["**/ios/Podfile", "**/ios/Podfile.lock"], 69 | "outputs": ["**/ios/Pods/**"] 70 | }, 71 | "lint": {}, 72 | "tsc": {}, 73 | "build": {} 74 | } 75 | } 76 | --------------------------------------------------------------------------------