diff --git a/example/src/App.tsx b/example/src/App.tsx
index 9635e09778..416a0d252b 100644
--- a/example/src/App.tsx
+++ b/example/src/App.tsx
@@ -123,7 +123,13 @@ const App = () => {
}}
/>
-
+ null,
+ }}
+ />
diff --git a/example/src/Examples/Breathe/Breathe.tsx b/example/src/Examples/Breathe/Breathe.tsx
index 70ee72aa67..9c51add014 100644
--- a/example/src/Examples/Breathe/Breathe.tsx
+++ b/example/src/Examples/Breathe/Breathe.tsx
@@ -1,43 +1,91 @@
-import React, { useEffect, useRef } from "react";
-import {
- gpu,
- SkiaDomView,
-} from "@shopify/react-native-skia";
-import { demo1 } from "./demo1/main";
+import React, { useEffect, useRef, useState } from "react";
+import { gpu, SkiaDomView, useImage } from "@shopify/react-native-skia";
+import { View } from "react-native";
+import { Gesture, GestureDetector } from "react-native-gesture-handler";
+import { useSharedValue, withSpring } from "react-native-reanimated";
+import type { SharedValue } from "react-native-reanimated";
-const triangleVertWGSL = `@vertex
-fn main(
- @builtin(vertex_index) VertexIndex : u32
-) -> @builtin(position) vec4f {
- var pos = array(
- vec2(0.0, 0.5),
- vec2(-0.5, -0.5),
- vec2(0.5, -0.5)
- );
+import { demo3 } from "./demo3";
+import { demo2 } from "./demo2";
+import { demo1 } from "./demo1/main";
+import { demo4 } from "./demo1/demo4";
+import { demo5 } from "./demo1/demo5";
+import { Bitmap, demo7 } from "./demo1/demo7";
+import { demo6 } from "./demo6/main";
- return vec4f(pos[VertexIndex], 0.0, 1.0);
-}
-`;
+const sf = 300;
+const springConfig = (velocity: number) => {
+ "worklet";
+ return {
+ mass: 1,
+ damping: 1,
+ stiffness: 100,
+ overshootClamping: false,
+ restDisplacementThreshold: 0.01,
+ restSpeedThreshold: 2,
+ velocity,
+ };
+};
+//import { demo6 } from "./demo6/main";
-const redFragWGSL = `@fragment
-fn main() -> @location(0) vec4f {
- return vec4(0.3, 0.6, 1.0, 1.0);
-}`;
+const draw = async (
+ context: GPUCanvasContext,
+ image: Bitmap,
+ rotateX: SharedValue,
+ rotateY: SharedValue
+) => {
+ const adapter = await gpu.requestAdapter();
+ const device = await adapter!.requestDevice();
+ const presentationFormat = "rgba8unorm";
+ context.configure({
+ device,
+ format: presentationFormat,
+ alphaMode: "premultiplied",
+ });
+ //await demo5(device, context, image);
+ await demo7(device, context, image, rotateX, rotateY);
+ //context.present();
+};
-const draw = async (ctx: GPUCanvasContext) => {
- await demo1(ctx);
- ctx.present();
+const usePixels = (mod: number) => {
+ const image = useImage(mod);
+ if (!image) {
+ return null;
+ }
+ return new Bitmap(
+ image.readPixels() as Uint8Array,
+ image.width(),
+ image.height()
+ );
};
export const Breathe = () => {
+ const image = usePixels(require("./demo6/react.png"));
+ const rotateX = useSharedValue(0);
+ const rotateY = useSharedValue(0);
const ref = useRef(null);
+ const gesture = Gesture.Pan()
+ .onChange((event) => {
+ rotateY.value += event.changeX / sf;
+ rotateX.value -= event.changeY / sf;
+ })
+ .onEnd(({ velocityX, velocityY }) => {
+ rotateX.value = withSpring(0, springConfig(velocityY / sf));
+ rotateY.value = withSpring(0, springConfig(velocityX / sf));
+ });
useEffect(() => {
setTimeout(() => {
- const ctx = ref.current!.getWGPUContext();
- draw(ctx);
+ if (image && ref.current) {
+ const ctx = ref.current.getWGPUContext();
+ draw(ctx, image, rotateX, rotateY);
+ }
}, 1000);
- }, []);
+ }, [image]);
return (
-
+
+
+
+
+
);
};
diff --git a/example/src/Examples/Breathe/demo1/backup.ts b/example/src/Examples/Breathe/demo1/backup.ts
new file mode 100644
index 0000000000..0c7e8e3b50
--- /dev/null
+++ b/example/src/Examples/Breathe/demo1/backup.ts
@@ -0,0 +1,175 @@
+import { mat4, vec3 } from 'wgpu-matrix';
+
+import {
+ cubeVertexArray,
+ cubeVertexSize,
+ cubeUVOffset,
+ cubePositionOffset,
+ cubeVertexCount,
+} from './cube';
+
+import {basicVertWGSL, vertexPositionColorWGSL} from './shaders';
+import { Dimensions } from 'react-native';
+
+const {width, height} = Dimensions.get("window");
+
+export const demo1 = async (device: GPUDevice, context: GPUCanvasContext) => {
+
+// Create a vertex buffer from the cube data.
+const verticesBuffer = device.createBuffer({
+ size: cubeVertexArray.byteLength,
+ usage: 32,//GPUBufferUsage.VERTEX,
+ mappedAtCreation: true,
+});
+
+new Float32Array(verticesBuffer.getMappedRange(0, cubeVertexArray.byteLength)).set(cubeVertexArray);
+verticesBuffer.unmap();
+const pipeline = device.createRenderPipeline({
+ layout: 'auto',
+ vertex: {
+ module: device.createShaderModule({
+ code: basicVertWGSL,
+ }),
+ entryPoint: "main",
+ buffers: [
+ {
+ arrayStride: cubeVertexSize,
+ attributes: [
+ {
+ // position
+ shaderLocation: 0,
+ offset: cubePositionOffset,
+ format: 'float32x4',
+ },
+ {
+ // uv
+ shaderLocation: 1,
+ offset: cubeUVOffset,
+ format: 'float32x2',
+ },
+ ],
+ },
+ ],
+ },
+ fragment: {
+ module: device.createShaderModule({
+ code: vertexPositionColorWGSL,
+ }),
+ entryPoint: "main",
+ targets: [
+ {
+ format: 'rgba8unorm',
+ },
+ ],
+ },
+ primitive: {
+ topology: 'triangle-list',
+
+ // Backface culling since the cube is solid piece of geometry.
+ // Faces pointing away from the camera will be occluded by faces
+ // pointing toward the camera.
+ cullMode: 'back',
+ },
+
+ // Enable depth testing so that the fragment closest to the camera
+ // is rendered in front.
+ depthStencil: {
+ depthWriteEnabled: true,
+ depthCompare: 'less',
+ format: 'depth24plus',
+ },
+});
+
+const depthTexture = device.createTexture({
+ size: { width, height },
+ format: 'depth24plus',
+ usage: 16,//GPUTextureUsage.RENDER_ATTACHMENT,
+});
+
+const uniformBufferSize = 4 * 16; // 4x4 matrix
+const uniformBuffer = device.createBuffer({
+ size: uniformBufferSize,
+ usage: 72,//GPUBufferUsage.UNIFORM | GPUBufferUsage.COPY_DST,
+ mappedAtCreation: false,
+});
+const uniformBindGroup = device.createBindGroup({
+ layout: pipeline.getBindGroupLayout(0),
+ entries: [
+ {
+ binding: 0,
+ buffer: uniformBuffer,
+ offset: 0,
+ size: uniformBufferSize,
+ },
+ ],
+});
+
+const renderPassDescriptor: GPURenderPassDescriptor = {
+ colorAttachments: [
+ {
+ view: undefined, // Assigned later
+
+ clearValue: [0.5, 0.5, 0.5, 1.0],
+ loadOp: 'clear',
+ storeOp: 'store',
+ },
+ ],
+ depthStencilAttachment: {
+ view: depthTexture.createView(),
+
+ depthClearValue: 1.0,
+ depthLoadOp: 'clear',
+ depthStoreOp: 'store',
+ },
+};
+
+const aspect = width / height;
+const projectionMatrix = mat4.perspective((2 * Math.PI) / 5, aspect, 1, 100.0);
+const modelViewProjectionMatrix = mat4.create();
+
+function getTransformationMatrix() {
+ const viewMatrix = mat4.identity();
+ mat4.translate(viewMatrix, vec3.fromValues(0, 0, -4), viewMatrix);
+ const now = Date.now() / 1000;
+ mat4.rotate(
+ viewMatrix,
+ vec3.fromValues(Math.sin(now), Math.cos(now), 0),
+ 1,
+ viewMatrix
+ );
+
+ mat4.multiply(projectionMatrix, viewMatrix, modelViewProjectionMatrix);
+
+ return modelViewProjectionMatrix as Float32Array;
+}
+
+async function frame() {
+ const transformationMatrix = getTransformationMatrix();
+ device.queue.writeBuffer(
+ uniformBuffer,
+ 0,
+ transformationMatrix.buffer,
+ 0,
+ transformationMatrix.byteLength
+ );
+
+ renderPassDescriptor.colorAttachments[0].view = context
+ .getCurrentTexture()
+ .createView();
+
+ const commandEncoder = device.createCommandEncoder();
+ const passEncoder = commandEncoder.beginRenderPass(renderPassDescriptor);
+ //passEncoder.pushDebugGroup("mygroupmarker");
+ passEncoder.setPipeline(pipeline);
+ passEncoder.setBindGroup(0, uniformBindGroup);
+ passEncoder.setVertexBuffer(0, verticesBuffer, 0, cubeVertexArray.byteLength);
+ passEncoder.draw(cubeVertexCount);
+ //passEncoder.popDebugGroup();
+ passEncoder.end();
+ device.queue.submit([commandEncoder.finish()]);
+ await device.queue.onSubmittedWorkDone();
+ console.log("DONE!");
+ //requestAnimationFrame(frame);
+}
+requestAnimationFrame(frame);
+};
\ No newline at end of file
diff --git a/example/src/Examples/Breathe/demo1/demo4.ts b/example/src/Examples/Breathe/demo1/demo4.ts
new file mode 100644
index 0000000000..27700586cc
--- /dev/null
+++ b/example/src/Examples/Breathe/demo1/demo4.ts
@@ -0,0 +1,177 @@
+import { mat4, vec3 } from "wgpu-matrix";
+import { Dimensions } from "react-native";
+
+import {
+ cubeVertexArray,
+ cubeVertexSize,
+ cubeUVOffset,
+ cubePositionOffset,
+ cubeVertexCount,
+} from "./cube";
+import { basicVertWGSL, vertexPositionColorWGSL } from "./shaders";
+
+const { width, height } = Dimensions.get("window");
+const presentationFormat = "rgba8unorm";
+const aspect = width / height;
+
+export const demo4 = async (device: GPUDevice, context: GPUCanvasContext) => {
+ // Create a vertex buffer from the cube data.
+
+ // Create a vertex buffer from the cube data.
+ const verticesBuffer = device.createBuffer({
+ size: cubeVertexArray.byteLength,
+ usage: GPUBufferUsage.VERTEX,
+ mappedAtCreation: true,
+ });
+ new Float32Array(verticesBuffer.getMappedRange()).set(cubeVertexArray);
+ verticesBuffer.unmap();
+
+ const pipeline = device.createRenderPipeline({
+ layout: "auto",
+ vertex: {
+ module: device.createShaderModule({
+ code: basicVertWGSL,
+ }),
+ entryPoint: "main",
+ buffers: [
+ {
+ arrayStride: cubeVertexSize,
+ attributes: [
+ {
+ // position
+ shaderLocation: 0,
+ offset: cubePositionOffset,
+ format: "float32x4",
+ },
+ {
+ // uv
+ shaderLocation: 1,
+ offset: cubeUVOffset,
+ format: "float32x2",
+ },
+ ],
+ },
+ ],
+ },
+ fragment: {
+ module: device.createShaderModule({
+ code: vertexPositionColorWGSL,
+ }),
+ entryPoint: "main",
+ targets: [
+ {
+ format: presentationFormat,
+ },
+ ],
+ },
+ primitive: {
+ topology: "triangle-list",
+
+ // Backface culling since the cube is solid piece of geometry.
+ // Faces pointing away from the camera will be occluded by faces
+ // pointing toward the camera.
+ cullMode: "back",
+ },
+
+ // Enable depth testing so that the fragment closest to the camera
+ // is rendered in front.
+ depthStencil: {
+ depthWriteEnabled: true,
+ depthCompare: "less",
+ format: "depth24plus",
+ },
+ });
+
+ const depthTexture = device.createTexture({
+ size: { width, height },
+ format: "depth24plus",
+ usage: GPUTextureUsage.RENDER_ATTACHMENT,
+ });
+
+ const uniformBufferSize = 4 * 16; // 4x4 matrix
+ const uniformBuffer = device.createBuffer({
+ size: uniformBufferSize,
+ usage: GPUBufferUsage.UNIFORM | GPUBufferUsage.COPY_DST,
+ });
+
+ const uniformBindGroup = device.createBindGroup({
+ layout: pipeline.getBindGroupLayout(0),
+ entries: [
+ {
+ binding: 0,
+ resource: {
+ buffer: uniformBuffer,
+ },
+ },
+ ],
+ });
+
+ const renderPassDescriptor: GPURenderPassDescriptor = {
+ colorAttachments: [
+ {
+ view: undefined, // Assigned later
+
+ clearValue: [0.5, 0.5, 0.5, 1.0],
+ loadOp: "clear",
+ storeOp: "store",
+ },
+ ],
+ depthStencilAttachment: {
+ view: depthTexture.createView(),
+
+ depthClearValue: 1.0,
+ depthLoadOp: "clear",
+ depthStoreOp: "store",
+ },
+ };
+
+ const projectionMatrix = mat4.perspective(
+ (2 * Math.PI) / 5,
+ aspect,
+ 1,
+ 100.0
+ );
+ const modelViewProjectionMatrix = mat4.create();
+
+ function getTransformationMatrix() {
+ const viewMatrix = mat4.identity();
+ mat4.translate(viewMatrix, vec3.fromValues(0, 0, -4), viewMatrix);
+ const now = Date.now() / 1000;
+ mat4.rotate(
+ viewMatrix,
+ vec3.fromValues(Math.sin(now), Math.cos(now), 0),
+ 1,
+ viewMatrix
+ );
+
+ mat4.multiply(projectionMatrix, viewMatrix, modelViewProjectionMatrix);
+
+ return modelViewProjectionMatrix as Float32Array;
+ }
+
+ function frame() {
+ const transformationMatrix = getTransformationMatrix();
+ device.queue.writeBuffer(
+ uniformBuffer,
+ 0,
+ transformationMatrix.buffer,
+ transformationMatrix.byteOffset,
+ transformationMatrix.byteLength
+ );
+ renderPassDescriptor.colorAttachments[0].view = context
+ .getCurrentTexture()
+ .createView();
+
+ const commandEncoder = device.createCommandEncoder();
+ const passEncoder = commandEncoder.beginRenderPass(renderPassDescriptor);
+ passEncoder.setPipeline(pipeline);
+ passEncoder.setBindGroup(0, uniformBindGroup);
+ passEncoder.setVertexBuffer(0, verticesBuffer);
+ passEncoder.draw(cubeVertexCount);
+ passEncoder.end();
+ device.queue.submit([commandEncoder.finish()]);
+ context.present();
+ requestAnimationFrame(frame);
+ }
+ requestAnimationFrame(frame);
+};
diff --git a/example/src/Examples/Breathe/demo1/demo5.ts b/example/src/Examples/Breathe/demo1/demo5.ts
new file mode 100644
index 0000000000..36d66bc2bc
--- /dev/null
+++ b/example/src/Examples/Breathe/demo1/demo5.ts
@@ -0,0 +1,222 @@
+import { mat4, vec3 } from "wgpu-matrix";
+import { Dimensions } from "react-native";
+
+import {
+ cubeVertexArray,
+ cubeVertexSize,
+ cubeUVOffset,
+ cubePositionOffset,
+ cubeVertexCount,
+} from "./cube";
+import { instancedVertWGSL, vertexPositionColorWGSL } from "./shaders";
+
+const { width, height } = Dimensions.get("window");
+
+export const demo5 = async (device: GPUDevice, context: GPUCanvasContext) => {
+ // Create a vertex buffer from the cube data.
+ const verticesBuffer = device.createBuffer({
+ size: cubeVertexArray.byteLength,
+ usage: GPUBufferUsage.VERTEX,
+ mappedAtCreation: true,
+ });
+ new Float32Array(verticesBuffer.getMappedRange()).set(cubeVertexArray);
+ verticesBuffer.unmap();
+
+ const pipeline = device.createRenderPipeline({
+ layout: "auto",
+ vertex: {
+ module: device.createShaderModule({
+ code: instancedVertWGSL,
+ }),
+ entryPoint: "main",
+ buffers: [
+ {
+ arrayStride: cubeVertexSize,
+ attributes: [
+ {
+ // position
+ shaderLocation: 0,
+ offset: cubePositionOffset,
+ format: "float32x4",
+ },
+ {
+ // uv
+ shaderLocation: 1,
+ offset: cubeUVOffset,
+ format: "float32x2",
+ },
+ ],
+ },
+ ],
+ },
+ fragment: {
+ module: device.createShaderModule({
+ code: vertexPositionColorWGSL,
+ }),
+ entryPoint: "main",
+ targets: [
+ {
+ format: "rgba8unorm",
+ },
+ ],
+ },
+ primitive: {
+ topology: "triangle-list",
+
+ // Backface culling since the cube is solid piece of geometry.
+ // Faces pointing away from the camera will be occluded by faces
+ // pointing toward the camera.
+ cullMode: "back",
+ },
+
+ // Enable depth testing so that the fragment closest to the camera
+ // is rendered in front.
+ // depthStencil: {
+ // depthWriteEnabled: true,
+ // depthCompare: 'less',
+ // format: 'depth24plus',
+ // },
+ });
+
+ // const depthTexture = device.createTexture({
+ // size: { width, height },
+ // format: 'depth24plus',
+ // usage: GPUTextureUsage.RENDER_ATTACHMENT,
+ // });
+
+ const xCount = 4;
+ const yCount = 4;
+ const numInstances = xCount * yCount;
+ const matrixFloatCount = 16; // 4x4 matrix
+ const matrixSize = 4 * matrixFloatCount;
+ const uniformBufferSize = numInstances * matrixSize;
+
+ // Allocate a buffer large enough to hold transforms for every
+ // instance.
+ const uniformBuffer = device.createBuffer({
+ size: uniformBufferSize,
+ usage: GPUBufferUsage.UNIFORM | GPUBufferUsage.COPY_DST,
+ });
+
+ const uniformBindGroup = device.createBindGroup({
+ layout: pipeline.getBindGroupLayout(0),
+ entries: [
+ {
+ binding: 0,
+ resource: {
+ buffer: uniformBuffer,
+ },
+ },
+ ],
+ });
+
+ const aspect = width / height;
+ const projectionMatrix = mat4.perspective(
+ (2 * Math.PI) / 5,
+ aspect,
+ 1,
+ 100.0
+ );
+
+ type Mat4 = mat4.default;
+ const modelMatrices = new Array(numInstances);
+ const mvpMatricesData = new Float32Array(matrixFloatCount * numInstances);
+
+ const step = 4.0;
+
+ // Initialize the matrix data for every instance.
+ let m = 0;
+ for (let x = 0; x < xCount; x++) {
+ for (let y = 0; y < yCount; y++) {
+ modelMatrices[m] = mat4.translation(
+ vec3.fromValues(
+ step * (x - xCount / 2 + 0.5),
+ step * (y - yCount / 2 + 0.5),
+ 0
+ )
+ );
+ m++;
+ }
+ }
+
+ const viewMatrix = mat4.translation(vec3.fromValues(0, 0, -12));
+
+ const tmpMat4 = mat4.create();
+
+ // Update the transformation matrix data for each instance.
+ function updateTransformationMatrix() {
+ const now = Date.now() / 1000;
+
+ let m = 0,
+ i = 0;
+ for (let x = 0; x < xCount; x++) {
+ for (let y = 0; y < yCount; y++) {
+ mat4.rotate(
+ modelMatrices[i],
+ vec3.fromValues(
+ Math.sin((x + 0.5) * now),
+ Math.cos((y + 0.5) * now),
+ 0
+ ),
+ 1,
+ tmpMat4
+ );
+
+ mat4.multiply(viewMatrix, tmpMat4, tmpMat4);
+ mat4.multiply(projectionMatrix, tmpMat4, tmpMat4);
+
+ mvpMatricesData.set(tmpMat4, m);
+
+ i++;
+ m += matrixFloatCount;
+ }
+ }
+ }
+
+ const renderPassDescriptor: GPURenderPassDescriptor = {
+ colorAttachments: [
+ {
+ view: undefined, // Assigned later
+
+ clearValue: [0.5, 0.5, 0.5, 1.0],
+ loadOp: "clear",
+ storeOp: "store",
+ },
+ ],
+ // depthStencilAttachment: {
+ // view: depthTexture.createView(),
+
+ // depthClearValue: 1.0,
+ // depthLoadOp: 'clear',
+ // depthStoreOp: 'store',
+ // },
+ };
+
+ function frame() {
+ // Update the matrix data.
+ updateTransformationMatrix();
+ device.queue.writeBuffer(
+ uniformBuffer,
+ 0,
+ mvpMatricesData.buffer,
+ mvpMatricesData.byteOffset,
+ mvpMatricesData.byteLength
+ );
+
+ renderPassDescriptor.colorAttachments[0].view = context
+ .getCurrentTexture()
+ .createView();
+
+ const commandEncoder = device.createCommandEncoder();
+ const passEncoder = commandEncoder.beginRenderPass(renderPassDescriptor);
+ passEncoder.setPipeline(pipeline);
+ passEncoder.setBindGroup(0, uniformBindGroup);
+ passEncoder.setVertexBuffer(0, verticesBuffer);
+ passEncoder.draw(cubeVertexCount, numInstances, 0, 0);
+ passEncoder.end();
+ device.queue.submit([commandEncoder.finish()]);
+ context.present();
+ requestAnimationFrame(frame);
+ }
+ requestAnimationFrame(frame);
+};
diff --git a/example/src/Examples/Breathe/demo1/demo7.ts b/example/src/Examples/Breathe/demo1/demo7.ts
new file mode 100644
index 0000000000..b782cc0ce7
--- /dev/null
+++ b/example/src/Examples/Breathe/demo1/demo7.ts
@@ -0,0 +1,194 @@
+import { Dimensions } from "react-native";
+
+const { width, height } = Dimensions.get("window");
+
+export class Bitmap {
+ constructor(
+ public data: Uint8Array,
+ public width: number,
+ public height: number
+ ) {
+ this.flipYAxis();
+ }
+ flipYAxis(): void {
+ const rowLength = this.width * 4; // 4 bytes per pixel (RGBA8)
+ const tempRow = new Uint8Array(rowLength);
+
+ for (let y = 0; y < this.height / 2; y++) {
+ const topRowIndex = y * rowLength;
+ const bottomRowIndex = (this.height - y - 1) * rowLength;
+
+ // Swap rows
+ tempRow.set(this.data.subarray(topRowIndex, topRowIndex + rowLength));
+ this.data.copyWithin(
+ topRowIndex,
+ bottomRowIndex,
+ bottomRowIndex + rowLength
+ );
+ this.data.set(tempRow, bottomRowIndex);
+ }
+ }
+}
+
+export const demo7 = async (
+ device: GPUDevice,
+ context: GPUCanvasContext,
+ img: Bitmap
+) => {
+ const presentationFormat = "rgba8unorm";
+
+ // First Matrix
+
+ const rows1 = 512;
+ const columns1 = 512;
+ const firstMatrix = new Float32Array(rows1 * columns1 + 2);
+ firstMatrix[0] = rows1;
+ firstMatrix[1] = columns1;
+ for (let i = 2; i < firstMatrix.length; i++) {
+ firstMatrix[i] = Math.random();
+ }
+
+ const gpuBufferFirstMatrix = device.createBuffer({
+ mappedAtCreation: true,
+ size: firstMatrix.byteLength,
+ usage: GPUBufferUsage.STORAGE,
+ });
+ const arrayBufferFirstMatrix = gpuBufferFirstMatrix.getMappedRange();
+ new Float32Array(arrayBufferFirstMatrix).set(firstMatrix);
+ gpuBufferFirstMatrix.unmap();
+
+ // Second Matrix
+
+ const secondMatrix = new Float32Array(rows1 * columns1 + 2);
+ secondMatrix[0] = rows1;
+ secondMatrix[1] = columns1;
+ for (let i = 2; i < secondMatrix.length; i++) {
+ secondMatrix[i] = Math.random();
+ }
+
+ const gpuBufferSecondMatrix = device.createBuffer({
+ mappedAtCreation: true,
+ size: secondMatrix.byteLength,
+ usage: GPUBufferUsage.STORAGE,
+ });
+ const arrayBufferSecondMatrix = gpuBufferSecondMatrix.getMappedRange();
+ new Float32Array(arrayBufferSecondMatrix).set(secondMatrix);
+ gpuBufferSecondMatrix.unmap();
+
+ // Result Matrix
+
+ const resultMatrixBufferSize =
+ Float32Array.BYTES_PER_ELEMENT * (2 + firstMatrix[0] * secondMatrix[1]);
+ const resultMatrixBuffer = device.createBuffer({
+ size: resultMatrixBufferSize,
+ usage: GPUBufferUsage.STORAGE | GPUBufferUsage.COPY_SRC,
+ });
+
+ // Compute shader code
+
+ const shaderModule = device.createShaderModule({
+ code: `
+ struct Matrix {
+ size : vec2,
+ numbers: array,
+ }
+
+ @group(0) @binding(0) var firstMatrix : Matrix;
+ @group(0) @binding(1) var secondMatrix : Matrix;
+ @group(0) @binding(2) var resultMatrix : Matrix;
+
+ @compute @workgroup_size(8, 8)
+ fn main(@builtin(global_invocation_id) global_id : vec3) {
+ // Guard against out-of-bounds work group sizes
+ if (global_id.x >= u32(firstMatrix.size.x) || global_id.y >= u32(secondMatrix.size.y)) {
+ return;
+ }
+
+ resultMatrix.size = vec2(firstMatrix.size.x, secondMatrix.size.y);
+
+ let resultCell = vec2(global_id.x, global_id.y);
+ var result = 0.0;
+ for (var i = 0u; i < u32(firstMatrix.size.y); i = i + 1u) {
+ let a = i + resultCell.x * u32(firstMatrix.size.y);
+ let b = resultCell.y + i * u32(secondMatrix.size.y);
+ result = result + firstMatrix.numbers[a] * secondMatrix.numbers[b];
+ }
+
+ let index = resultCell.y + resultCell.x * u32(secondMatrix.size.y);
+ resultMatrix.numbers[index] = result;
+ }
+ `,
+ });
+
+ // Pipeline setup
+
+ const computePipeline = device.createComputePipeline({
+ layout: "auto",
+ compute: {
+ module: shaderModule,
+ entryPoint: "main",
+ },
+ });
+
+ // Bind group
+
+ const bindGroup = device.createBindGroup({
+ layout: computePipeline.getBindGroupLayout(0 /* index */),
+ entries: [
+ {
+ binding: 0,
+ resource: {
+ buffer: gpuBufferFirstMatrix,
+ },
+ },
+ {
+ binding: 1,
+ resource: {
+ buffer: gpuBufferSecondMatrix,
+ },
+ },
+ {
+ binding: 2,
+ resource: {
+ buffer: resultMatrixBuffer,
+ },
+ },
+ ],
+ });
+
+ // Commands submission
+
+ const commandEncoder = device.createCommandEncoder();
+
+ const passEncoder = commandEncoder.beginComputePass();
+ passEncoder.setPipeline(computePipeline);
+ passEncoder.setBindGroup(0, bindGroup);
+ const workgroupCountX = Math.ceil(rows1 / 8);
+ const workgroupCountY = Math.ceil(columns2 / 8);
+ passEncoder.dispatchWorkgroups(workgroupCountX, workgroupCountY);
+ passEncoder.end();
+
+ // Get a GPU buffer for reading in an unmapped state.
+ const gpuReadBuffer = device.createBuffer({
+ size: resultMatrixBufferSize,
+ usage: GPUBufferUsage.COPY_DST | GPUBufferUsage.MAP_READ,
+ });
+
+ // Encode commands for copying buffer to buffer.
+ commandEncoder.copyBufferToBuffer(
+ resultMatrixBuffer /* source buffer */,
+ 0 /* source offset */,
+ gpuReadBuffer /* destination buffer */,
+ 0 /* destination offset */,
+ resultMatrixBufferSize /* size */
+ );
+
+ // Submit GPU commands.
+ const gpuCommands = commandEncoder.finish();
+ device.queue.submit([gpuCommands]);
+
+ // Read buffer.
+ await gpuReadBuffer.mapAsync(GPUMapMode.READ);
+ const arrayBuffer = gpuReadBuffer.getMappedRange();
+ console.log(new Float32Array(arrayBuffer));
+};
diff --git a/example/src/Examples/Breathe/demo1/main.ts b/example/src/Examples/Breathe/demo1/main.ts
index e53d1ee12f..1bbae5a160 100644
--- a/example/src/Examples/Breathe/demo1/main.ts
+++ b/example/src/Examples/Breathe/demo1/main.ts
@@ -1,4 +1,5 @@
-import { mat4, vec3 } from 'wgpu-matrix';
+import { mat4, vec3 } from "wgpu-matrix";
+import { Dimensions } from "react-native";
import {
cubeVertexArray,
@@ -6,205 +7,173 @@ import {
cubeUVOffset,
cubePositionOffset,
cubeVertexCount,
-} from './cube';
-
-import {basicVertWGSL, vertexPositionColorWGSL} from './shaders';
-import { gpu } from '@shopify/react-native-skia';
-import { Dimensions } from 'react-native';
-
-const GPUBufferUsage = {
- None: 0x00000000,
- MapRead: 0x00000001,
- MapWrite: 0x00000002,
- CopyStr: 0x00000004,
- COPY_DST: 0x00000008,
- Index: 0x00000010,
- VERTEX: 0x00000020,
- UNIFORM: 0x00000040,
- Storage: 0x00000080,
- Indirect: 0x00000100,
- QueryResolve: 0x00000200,
- Force32: 0x7FFFFFFF
-};
-
-const GPUTextureUsage = {
- RENDER_ATTACHMENT: 0x00000010,
-}
-
-const {width, height} = Dimensions.get("window");
-
-export const demo1 = async (context: GPUCanvasContext) => {
- const adapter = await gpu.requestAdapter();
- const device = await adapter!.requestDevice();
- const presentationFormat = 'rgba8unorm';
-context.configure({
- device,
- format: presentationFormat,
- alphaMode: 'premultiplied',
-});
-
-// Create a vertex buffer from the cube data.
-const verticesBuffer = device.createBuffer({
- size: cubeVertexArray.byteLength,
- usage: GPUBufferUsage.VERTEX,
- mappedAtCreation: true,
-});
-
-const mappedRange = verticesBuffer.getMappedRange(0, cubeVertexArray.byteLength);
-new Float32Array(mappedRange).set(cubeVertexArray);
-verticesBuffer.unmap();
-
-const pipeline = device.createRenderPipeline({
- layout: 'auto',
- vertex: {
- module: device.createShaderModule({
- code: basicVertWGSL,
- }),
- entryPoint: "main",
- buffers: [
+} from "./cube";
+import { basicVertWGSL, vertexPositionColorWGSL } from "./shaders";
+
+const { width, height } = Dimensions.get("window");
+
+export const demo1 = async (device: GPUDevice, context: GPUCanvasContext) => {
+ // Create a vertex buffer from the cube data.
+ const verticesBuffer = device.createBuffer({
+ size: cubeVertexArray.byteLength,
+ usage: GPUBufferUsage.VERTEX,
+ mappedAtCreation: true,
+ });
+
+ new Float32Array(
+ verticesBuffer.getMappedRange(0, cubeVertexArray.byteLength)
+ ).set(cubeVertexArray);
+ verticesBuffer.unmap();
+ const pipeline = device.createRenderPipeline({
+ layout: "auto",
+ vertex: {
+ module: device.createShaderModule({
+ code: basicVertWGSL,
+ }),
+ entryPoint: "main",
+ buffers: [
+ {
+ arrayStride: cubeVertexSize,
+ attributes: [
+ {
+ // position
+ shaderLocation: 0,
+ offset: cubePositionOffset,
+ format: "float32x4",
+ },
+ {
+ // uv
+ shaderLocation: 1,
+ offset: cubeUVOffset,
+ format: "float32x2",
+ },
+ ],
+ },
+ ],
+ },
+ fragment: {
+ module: device.createShaderModule({
+ code: vertexPositionColorWGSL,
+ }),
+ entryPoint: "main",
+ targets: [
+ {
+ format: "rgba8unorm",
+ },
+ ],
+ },
+ // depthStencil: {
+ // depthWriteEnabled: true,
+ // depthCompare: "less",
+ // format: "depth24plus",
+ // },
+ primitive: {
+ topology: "triangle-list",
+ cullMode: "back",
+ },
+ });
+
+ // const depthTexture = device.createTexture({
+ // size: { width, height },
+ // format: "depth24plus",
+ // usage: GPUTextureUsage.RENDER_ATTACHMENT,
+ // });
+
+ const uniformBufferSize = 4 * 16; // 4x4 matrix
+ const uniformBuffer = device.createBuffer({
+ size: uniformBufferSize,
+ usage: GPUBufferUsage.UNIFORM | GPUBufferUsage.COPY_DST,
+ mappedAtCreation: false,
+ });
+ const uniformBindGroup = device.createBindGroup({
+ layout: pipeline.getBindGroupLayout(0),
+ entries: [
{
- arrayStride: cubeVertexSize,
- attributes: [
- {
- // position
- shaderLocation: 0,
- offset: cubePositionOffset,
- format: 'float32x4',
- },
- {
- // uv
- shaderLocation: 1,
- offset: cubeUVOffset,
- format: 'float32x2',
- },
- ],
+ binding: 0,
+ buffer: uniformBuffer,
+ offset: 0,
+ size: uniformBufferSize,
},
],
- },
- fragment: {
- module: device.createShaderModule({
- code: vertexPositionColorWGSL,
- }),
- entryPoint: "main",
- targets: [
+ });
+
+ const renderPassDescriptor: GPURenderPassDescriptor = {
+ colorAttachments: [
{
- format: presentationFormat,
+ view: undefined, // Assigned later
+
+ clearValue: [0.5, 0.5, 0.5, 1.0],
+ loadOp: "clear",
+ storeOp: "store",
},
],
- },
- primitive: {
- topology: 'triangle-list',
-
- // Backface culling since the cube is solid piece of geometry.
- // Faces pointing away from the camera will be occluded by faces
- // pointing toward the camera.
- cullMode: 'back',
- },
-
- // Enable depth testing so that the fragment closest to the camera
- // is rendered in front.
- depthStencil: {
- depthWriteEnabled: true,
- depthCompare: 'less',
- format: 'depth24plus',
- },
-});
-
-const depthTexture = device.createTexture({
- size: { width, height },
- format: 'depth24plus',
- usage: GPUTextureUsage.RENDER_ATTACHMENT,
-});
-
-
-const uniformBufferSize = 4 * 16; // 4x4 matrix
-const uniformBuffer = device.createBuffer({
- size: uniformBufferSize,
- usage: GPUBufferUsage.UNIFORM | GPUBufferUsage.COPY_DST,
- mappedAtCreation: false
-});
-
-console.log(pipeline.getBindGroupLayout(0))
-
-const uniformBindGroup = device.createBindGroup({
- layout: pipeline.getBindGroupLayout(0),
- entries: [
- {
- binding: 0,
- buffer: uniformBuffer,
- },
- ],
-});
-
-
-
-const renderPassDescriptor: GPURenderPassDescriptor = {
- colorAttachments: [
- {
- view: context
- .getCurrentTexture()
- .createView(), // Assigned later
-
- clearValue: [0.5, 0.5, 0.5, 1.0],
- loadOp: 'clear',
- storeOp: 'store',
- },
- ],
- depthStencilAttachment: {
- view: depthTexture.createView(),
-
- depthClearValue: 1.0,
- depthLoadOp: 'clear',
- depthStoreOp: 'store',
- },
-};
-
-console.log(renderPassDescriptor)
-
-const aspect = width / height;
-const projectionMatrix = mat4.perspective((2 * Math.PI) / 5, aspect, 1, 100.0);
-const modelViewProjectionMatrix = mat4.create();
-
-function getTransformationMatrix() {
- const viewMatrix = mat4.identity();
- mat4.translate(viewMatrix, vec3.fromValues(0, 0, -4), viewMatrix);
- const now = Date.now() / 1000;
- mat4.rotate(
- viewMatrix,
- vec3.fromValues(Math.sin(now), Math.cos(now), 0),
+ // depthStencilAttachment: {
+ // view: depthTexture.createView(),
+
+ // depthClearValue: 1.0,
+ // depthLoadOp: 'clear',
+ // depthStoreOp: 'store',
+ // },
+ };
+
+ const aspect = width / height;
+ const projectionMatrix = mat4.perspective(
+ (2 * Math.PI) / 5,
+ aspect,
1,
- viewMatrix
- );
-
- mat4.multiply(projectionMatrix, viewMatrix, modelViewProjectionMatrix);
-
- return modelViewProjectionMatrix as Float32Array;
-}
-
-function frame() {
- const transformationMatrix = getTransformationMatrix();
- device.queue.writeBuffer(
- uniformBuffer,
- 0,
- transformationMatrix.buffer,
- transformationMatrix.byteOffset,
- transformationMatrix.byteLength
+ 100.0
);
- // renderPassDescriptor.colorAttachments[0].view = context
- // .getCurrentTexture()
- // .createView();
-
- const commandEncoder = device.createCommandEncoder();
- const passEncoder = commandEncoder.beginRenderPass(renderPassDescriptor);
- passEncoder.setPipeline(pipeline);
- passEncoder.setBindGroup(0, uniformBindGroup);
- passEncoder.setVertexBuffer(0, verticesBuffer);
- passEncoder.draw(cubeVertexCount);
- passEncoder.end();
- device.queue.submit([commandEncoder.finish()]);
-
+ const modelViewProjectionMatrix = mat4.create();
+
+ function getTransformationMatrix() {
+ const viewMatrix = mat4.identity();
+ mat4.translate(viewMatrix, vec3.fromValues(0, 0, -4), viewMatrix);
+ const now = Date.now() / 1000;
+ mat4.rotate(
+ viewMatrix,
+ vec3.fromValues(Math.sin(now), Math.cos(now), 0),
+ 1,
+ viewMatrix
+ );
+
+ mat4.multiply(projectionMatrix, viewMatrix, modelViewProjectionMatrix);
+
+ return modelViewProjectionMatrix as Float32Array;
+ }
+
+ function frame() {
+ const transformationMatrix = getTransformationMatrix();
+ device.queue.writeBuffer(
+ uniformBuffer,
+ 0,
+ transformationMatrix.buffer,
+ 0,
+ transformationMatrix.byteLength
+ );
+
+ renderPassDescriptor.colorAttachments[0].view = context
+ .getCurrentTexture()
+ .createView();
+
+ const commandEncoder = device.createCommandEncoder();
+ const passEncoder = commandEncoder.beginRenderPass(renderPassDescriptor);
+ //passEncoder.pushDebugGroup("mygroupmarker");
+ passEncoder.setPipeline(pipeline);
+ passEncoder.setBindGroup(0, uniformBindGroup);
+ passEncoder.setVertexBuffer(
+ 0,
+ verticesBuffer,
+ 0,
+ cubeVertexArray.byteLength
+ );
+ passEncoder.draw(cubeVertexCount);
+ //passEncoder.popDebugGroup();
+ passEncoder.end();
+ device.queue.submit([commandEncoder.finish()]);
+ //await device.queue.onSubmittedWorkDone();
+ context.present();
+ console.log("DONE!");
+ requestAnimationFrame(frame);
+ }
requestAnimationFrame(frame);
-}
-requestAnimationFrame(frame);
-
-};
\ No newline at end of file
+};
diff --git a/example/src/Examples/Breathe/demo1/shaders.ts b/example/src/Examples/Breathe/demo1/shaders.ts
index ee8ad26a64..fb456d2698 100644
--- a/example/src/Examples/Breathe/demo1/shaders.ts
+++ b/example/src/Examples/Breathe/demo1/shaders.ts
@@ -27,4 +27,32 @@ fn main(
output.fragUV = uv;
output.fragPosition = 0.5 * (position + vec4(1.0, 1.0, 1.0, 1.0));
return output;
-}`;
\ No newline at end of file
+}
+`;
+
+export const instancedVertWGSL = `
+struct Uniforms {
+ modelViewProjectionMatrix : array,
+}
+
+@binding(0) @group(0) var uniforms : Uniforms;
+
+struct VertexOutput {
+ @builtin(position) Position : vec4f,
+ @location(0) fragUV : vec2f,
+ @location(1) fragPosition: vec4f,
+}
+
+@vertex
+fn main(
+ @builtin(instance_index) instanceIdx : u32,
+ @location(0) position : vec4f,
+ @location(1) uv : vec2f
+) -> VertexOutput {
+ var output : VertexOutput;
+ output.Position = uniforms.modelViewProjectionMatrix[instanceIdx] * position;
+ output.fragUV = uv;
+ output.fragPosition = 0.5 * (position + vec4(1.0));
+ return output;
+}
+`;
diff --git a/example/src/Examples/Breathe/demo2.ts b/example/src/Examples/Breathe/demo2.ts
new file mode 100644
index 0000000000..6b5b0d6eb5
--- /dev/null
+++ b/example/src/Examples/Breathe/demo2.ts
@@ -0,0 +1,69 @@
+import { gpu } from "@shopify/react-native-skia";
+
+const triangleVertWGSL = `@vertex
+fn main(
+ @builtin(vertex_index) VertexIndex : u32
+) -> @builtin(position) vec4f {
+ var pos = array(
+ vec2(0.0, 0.5),
+ vec2(-0.5, -0.5),
+ vec2(0.5, -0.5)
+ );
+
+ return vec4f(pos[VertexIndex], 0.0, 1.0);
+}
+`;
+
+const redFragWGSL = `@fragment
+fn main() -> @location(0) vec4f {
+ return vec4(0.3, 0.6, 1.0, 1.0);
+}`;
+
+export const demo2 = async (device, context: GPUCanvasContext) => {
+ const presentationFormat = "rgba8unorm";
+
+ const pipeline = device.createRenderPipeline({
+ layout: "auto",
+ vertex: {
+ module: device.createShaderModule({
+ code: triangleVertWGSL,
+ }),
+ entryPoint: "main",
+ },
+ fragment: {
+ module: device.createShaderModule({
+ code: redFragWGSL,
+ }),
+ entryPoint: "main",
+ targets: [
+ {
+ format: presentationFormat,
+ },
+ ],
+ },
+ primitive: {
+ topology: "triangle-list",
+ },
+ });
+
+ const commandEncoder = device.createCommandEncoder();
+ const textureView = context.getCurrentTexture().createView();
+
+ const renderPassDescriptor: GPURenderPassDescriptor = {
+ colorAttachments: [
+ {
+ view: textureView,
+ clearValue: [1.0, 0.0, 1.0, 1],
+ loadOp: "clear",
+ storeOp: "store",
+ },
+ ],
+ };
+
+ const passEncoder = commandEncoder.beginRenderPass(renderPassDescriptor);
+ passEncoder.setPipeline(pipeline);
+ passEncoder.draw(3);
+ passEncoder.end();
+
+ device.queue.submit([commandEncoder.finish()]);
+};
diff --git a/example/src/Examples/Breathe/demo3.tsx b/example/src/Examples/Breathe/demo3.tsx
new file mode 100644
index 0000000000..4fc9a392cf
--- /dev/null
+++ b/example/src/Examples/Breathe/demo3.tsx
@@ -0,0 +1,24 @@
+export const demo3 = async(device: GPUDevice, context: GPUCanvasContext) => {
+ // Create an array of data
+ const data = new Uint32Array([1.0, 2.0, 3.0, 4.0]);
+
+ // Create a GPU buffer and store data
+ const gpuBuffer = device.createBuffer({
+ size: data.byteLength,
+ usage: 9, //GPUBufferUsage.MAP_READ | GPUBufferUsage.COPY_DST
+ mappedAtCreation: false
+ });
+
+
+ // Copy data to the GPU buffer
+ device.queue.writeBuffer(gpuBuffer, 0, data.buffer, 0, data.byteLength);
+
+ await gpuBuffer.mapAsync(1, 0, data.byteLength); // GPUMapMode.READ
+ console.log("mapAsync done");
+ const arrayBuffer = gpuBuffer.getMappedRange(0, data.byteLength);
+ const readData = new Float32Array(arrayBuffer);
+
+ // // Output the read data
+ console.log('Data read from the buffer:', readData);
+ gpuBuffer.unmap();
+ };
\ No newline at end of file
diff --git a/example/src/Examples/Breathe/demo6/main.ts b/example/src/Examples/Breathe/demo6/main.ts
new file mode 100644
index 0000000000..568ffd1b5b
--- /dev/null
+++ b/example/src/Examples/Breathe/demo6/main.ts
@@ -0,0 +1,448 @@
+/* eslint-disable @typescript-eslint/ban-ts-comment */
+/* eslint-disable camelcase */
+import { mat4, vec3 } from "wgpu-matrix";
+import { Dimensions } from "react-native";
+import type { SharedValue } from "react-native-reanimated";
+
+import type { Bitmap } from "../demo1/demo7";
+
+import { probabilityMapWGSL } from "./probabilityMap";
+import { particleWGSL } from "./particle";
+
+const { width, height } = Dimensions.get("window");
+const canvas = { width, height };
+const presentationFormat = "rgba8unorm";
+
+export const demo6 = (
+ device: GPUDevice,
+ context: GPUCanvasContext,
+ imageBitmap: Bitmap,
+ rotateX: SharedValue,
+ rotateY: SharedValue
+) => {
+ const numParticles = 10000;
+ const particlePositionOffset = 0;
+ const particleColorOffset = 4 * 4;
+ const particleInstanceByteSize =
+ 3 * 4 + // position
+ 1 * 4 + // lifetime
+ 4 * 4 + // color
+ 3 * 4 + // velocity
+ 1 * 4 + // padding
+ 0;
+
+ context.configure({
+ device,
+ format: presentationFormat,
+ alphaMode: "premultiplied",
+ });
+
+ const particlesBuffer = device.createBuffer({
+ size: numParticles * particleInstanceByteSize,
+ usage: GPUBufferUsage.VERTEX | GPUBufferUsage.STORAGE,
+ });
+
+ const renderPipeline = device.createRenderPipeline({
+ layout: "auto",
+ vertex: {
+ module: device.createShaderModule({
+ code: particleWGSL,
+ }),
+ entryPoint: "vs_main",
+ buffers: [
+ {
+ // instanced particles buffer
+ arrayStride: particleInstanceByteSize,
+ stepMode: "instance",
+ attributes: [
+ {
+ // position
+ shaderLocation: 0,
+ offset: particlePositionOffset,
+ format: "float32x3",
+ },
+ {
+ // color
+ shaderLocation: 1,
+ offset: particleColorOffset,
+ format: "float32x4",
+ },
+ ],
+ },
+ {
+ // quad vertex buffer
+ arrayStride: 2 * 4, // vec2f
+ stepMode: "vertex",
+ attributes: [
+ {
+ // vertex positions
+ shaderLocation: 2,
+ offset: 0,
+ format: "float32x2",
+ },
+ ],
+ },
+ ],
+ },
+ fragment: {
+ module: device.createShaderModule({
+ code: particleWGSL,
+ }),
+ entryPoint: "fs_main",
+ targets: [
+ {
+ format: presentationFormat,
+ blend: {
+ color: {
+ srcFactor: "src-alpha",
+ dstFactor: "one",
+ operation: "add",
+ },
+ alpha: {
+ srcFactor: "zero",
+ dstFactor: "one",
+ operation: "add",
+ },
+ },
+ },
+ ],
+ },
+ primitive: {
+ topology: "triangle-list",
+ },
+
+ // depthStencil: {
+ // depthWriteEnabled: false,
+ // depthCompare: 'less',
+ // format: 'depth24plus',
+ // },
+ });
+
+ // const depthTexture = device.createTexture({
+ // size: [canvas.width, canvas.height],
+ // format: 'depth24plus',
+ // usage: GPUTextureUsage.RENDER_ATTACHMENT,
+ // });
+
+ const uniformBufferSize =
+ 4 * 4 * 4 + // modelViewProjectionMatrix : mat4x4f
+ 3 * 4 + // right : vec3f
+ 4 + // padding
+ 3 * 4 + // up : vec3f
+ 4 + // padding
+ 0;
+ const uniformBuffer = device.createBuffer({
+ size: uniformBufferSize,
+ usage: GPUBufferUsage.UNIFORM | GPUBufferUsage.COPY_DST,
+ });
+
+ const uniformBindGroup = device.createBindGroup({
+ layout: renderPipeline.getBindGroupLayout(0),
+ entries: [
+ {
+ binding: 0,
+ resource: {
+ buffer: uniformBuffer,
+ },
+ },
+ ],
+ });
+
+ const renderPassDescriptor: GPURenderPassDescriptor = {
+ colorAttachments: [
+ {
+ view: undefined, // Assigned later
+ clearValue: [0, 0, 0, 1],
+ loadOp: "clear",
+ storeOp: "store",
+ },
+ ],
+ // depthStencilAttachment: {
+ // view: depthTexture.createView(),
+
+ // depthClearValue: 1.0,
+ // depthLoadOp: 'clear',
+ // depthStoreOp: 'store',
+ // },
+ };
+
+ //////////////////////////////////////////////////////////////////////////////
+ // Quad vertex buffer
+ //////////////////////////////////////////////////////////////////////////////
+ const quadVertexBuffer = device.createBuffer({
+ size: 6 * 2 * 4, // 6x vec2f
+ usage: GPUBufferUsage.VERTEX,
+ mappedAtCreation: true,
+ });
+ // prettier-ignore
+ const vertexData = [
+ -1.0, -1.0, +1.0, -1.0, -1.0, +1.0, -1.0, +1.0, +1.0, -1.0, +1.0, +1.0,
+];
+ new Float32Array(quadVertexBuffer.getMappedRange()).set(vertexData);
+ quadVertexBuffer.unmap();
+
+ //////////////////////////////////////////////////////////////////////////////
+ // Texture
+ //////////////////////////////////////////////////////////////////////////////
+ let texture: GPUTexture;
+ let textureWidth = 1;
+ let textureHeight = 1;
+ let numMipLevels = 1;
+ {
+ // Calculate number of mip levels required to generate the probability map
+ while (
+ textureWidth < imageBitmap.width ||
+ textureHeight < imageBitmap.height
+ ) {
+ textureWidth *= 2;
+ textureHeight *= 2;
+ numMipLevels++;
+ }
+ texture = device.createTexture({
+ size: { width: imageBitmap.width, height: imageBitmap.height },
+ mipLevelCount: numMipLevels,
+ format: "rgba8unorm",
+ usage:
+ GPUTextureUsage.TEXTURE_BINDING |
+ GPUTextureUsage.STORAGE_BINDING |
+ GPUTextureUsage.COPY_DST |
+ GPUTextureUsage.RENDER_ATTACHMENT,
+ });
+ device.queue.writeTexture(
+ { texture: texture, mipLevel: 0, origin: { x: 0, y: 0, z: 0 } },
+ imageBitmap.data.buffer,
+ {
+ offset: 0,
+ bytesPerRow: 4 * imageBitmap.width,
+ rowsPerImage: imageBitmap.height,
+ },
+ { width: imageBitmap.width, height: imageBitmap.height }
+ );
+ }
+
+ //////////////////////////////////////////////////////////////////////////////
+ // Probability map generation
+ // The 0'th mip level of texture holds the color data and spawn-probability in
+ // the alpha channel. The mip levels 1..N are generated to hold spawn
+ // probabilities up to the top 1x1 mip level.
+ //////////////////////////////////////////////////////////////////////////////
+ {
+ const probabilityMapImportLevelPipeline = device.createComputePipeline({
+ layout: "auto",
+ compute: {
+ module: device.createShaderModule({ code: probabilityMapWGSL }),
+ entryPoint: "import_level",
+ },
+ });
+ const probabilityMapExportLevelPipeline = device.createComputePipeline({
+ layout: "auto",
+ compute: {
+ module: device.createShaderModule({ code: probabilityMapWGSL }),
+ entryPoint: "export_level",
+ },
+ });
+
+ const probabilityMapUBOBufferSize =
+ 1 * 4 + // stride
+ 3 * 4 + // padding
+ 0;
+ const probabilityMapUBOBuffer = device.createBuffer({
+ size: probabilityMapUBOBufferSize,
+ usage: GPUBufferUsage.UNIFORM | GPUBufferUsage.COPY_DST,
+ });
+ const buffer_a = device.createBuffer({
+ size: textureWidth * textureHeight * 4,
+ usage: GPUBufferUsage.STORAGE,
+ });
+ const buffer_b = device.createBuffer({
+ size: textureWidth * textureHeight * 4,
+ usage: GPUBufferUsage.STORAGE,
+ });
+ device.queue.writeBuffer(
+ probabilityMapUBOBuffer,
+ 0,
+ new Int32Array([textureWidth]).buffer
+ );
+ const commandEncoder = device.createCommandEncoder();
+ for (let level = 0; level < numMipLevels; level++) {
+ const levelWidth = textureWidth >> level;
+ const levelHeight = textureHeight >> level;
+ const pipeline =
+ level == 0
+ ? probabilityMapImportLevelPipeline.getBindGroupLayout(0)
+ : probabilityMapExportLevelPipeline.getBindGroupLayout(0);
+ const probabilityMapBindGroup = device.createBindGroup({
+ layout: pipeline,
+ entries: [
+ {
+ // ubo
+ binding: 0,
+ resource: { buffer: probabilityMapUBOBuffer },
+ },
+ {
+ // buf_in
+ binding: 1,
+ resource: { buffer: level & 1 ? buffer_a : buffer_b },
+ },
+ {
+ // buf_out
+ binding: 2,
+ resource: { buffer: level & 1 ? buffer_b : buffer_a },
+ },
+ {
+ // tex_in / tex_out
+ binding: 3,
+ resource: texture.createView({
+ format: "rgba8unorm",
+ dimension: "2d",
+ baseMipLevel: level,
+ mipLevelCount: 1,
+ }),
+ },
+ ],
+ });
+ if (level == 0) {
+ const passEncoder = commandEncoder.beginComputePass();
+ passEncoder.setPipeline(probabilityMapImportLevelPipeline);
+ passEncoder.setBindGroup(0, probabilityMapBindGroup);
+ passEncoder.dispatchWorkgroups(Math.ceil(levelWidth / 64), levelHeight);
+ passEncoder.end();
+ } else {
+ const passEncoder = commandEncoder.beginComputePass();
+ passEncoder.setPipeline(probabilityMapExportLevelPipeline);
+ passEncoder.setBindGroup(0, probabilityMapBindGroup);
+ passEncoder.dispatchWorkgroups(Math.ceil(levelWidth / 64), levelHeight);
+ passEncoder.end();
+ }
+ }
+ device.queue.submit([commandEncoder.finish()]);
+ }
+
+ //////////////////////////////////////////////////////////////////////////////
+ // Simulation compute pipeline
+ //////////////////////////////////////////////////////////////////////////////
+ const simulationParams = {
+ simulate: true,
+ deltaTime: 0.04,
+ };
+
+ const simulationUBOBufferSize =
+ 1 * 4 + // deltaTime
+ 3 * 4 + // padding
+ 4 * 4 + // seed
+ 0;
+ const simulationUBOBuffer = device.createBuffer({
+ size: simulationUBOBufferSize,
+ usage: GPUBufferUsage.UNIFORM | GPUBufferUsage.COPY_DST,
+ });
+
+ const computePipeline = device.createComputePipeline({
+ layout: "auto",
+ compute: {
+ module: device.createShaderModule({
+ code: particleWGSL,
+ }),
+ entryPoint: "simulate",
+ },
+ });
+ const computeBindGroup = device.createBindGroup({
+ layout: computePipeline.getBindGroupLayout(0),
+ entries: [
+ {
+ binding: 0,
+ resource: {
+ buffer: simulationUBOBuffer,
+ },
+ },
+ {
+ binding: 1,
+ resource: {
+ buffer: particlesBuffer,
+ offset: 0,
+ size: numParticles * particleInstanceByteSize,
+ },
+ },
+ {
+ binding: 2,
+ resource: texture.createView(),
+ },
+ ],
+ });
+
+ const aspect = canvas.width / canvas.height;
+ const projection = mat4.perspective((2 * Math.PI) / 5, aspect, 1, 100.0);
+ const view = mat4.create();
+ const mvp = mat4.create();
+
+ function frame() {
+ device.queue.writeBuffer(
+ simulationUBOBuffer,
+ 0,
+ new Float32Array([
+ simulationParams.simulate ? simulationParams.deltaTime : 0.0,
+ 0.0,
+ 0.0,
+ 0.0, // padding
+ Math.random() * 100,
+ Math.random() * 100, // seed.xy
+ 1 + Math.random(),
+ 1 + Math.random(), // seed.zw
+ ]).buffer
+ );
+
+ mat4.identity(view);
+ mat4.translate(view, vec3.fromValues(0, 0, -3), view);
+ mat4.rotateX(view, Math.PI + rotateX.value, view);
+ mat4.rotateY(view, rotateY.value, view);
+ mat4.multiply(projection, view, mvp);
+
+ // prettier-ignore
+ device.queue.writeBuffer(
+ uniformBuffer,
+ 0,
+ new Float32Array([
+ // modelViewProjectionMatrix
+ mvp[0], mvp[1], mvp[2], mvp[3],
+ mvp[4], mvp[5], mvp[6], mvp[7],
+ mvp[8], mvp[9], mvp[10], mvp[11],
+ mvp[12], mvp[13], mvp[14], mvp[15],
+
+ view[0], view[4], view[8], // right
+
+ 0, // padding
+
+ view[1], view[5], view[9], // up
+
+ 0, // padding
+ ]).buffer
+ );
+ const swapChainTexture = context.getCurrentTexture();
+ // @ts-expect-error
+ renderPassDescriptor.colorAttachments[0].view =
+ swapChainTexture.createView();
+
+ const commandEncoder = device.createCommandEncoder();
+ {
+ const passEncoder = commandEncoder.beginComputePass();
+ passEncoder.setPipeline(computePipeline);
+ passEncoder.setBindGroup(0, computeBindGroup);
+ passEncoder.dispatchWorkgroups(Math.ceil(numParticles / 64));
+ passEncoder.end();
+ }
+ {
+ const passEncoder = commandEncoder.beginRenderPass(renderPassDescriptor);
+ passEncoder.setPipeline(renderPipeline);
+ passEncoder.setBindGroup(0, uniformBindGroup);
+ passEncoder.setVertexBuffer(0, particlesBuffer);
+ passEncoder.setVertexBuffer(1, quadVertexBuffer);
+ passEncoder.draw(6, numParticles, 0, 0);
+ passEncoder.end();
+ }
+
+ device.queue.submit([commandEncoder.finish()]);
+ // @ts-expect-error
+ context.present();
+ requestAnimationFrame(frame);
+ }
+ requestAnimationFrame(frame);
+};
diff --git a/example/src/Examples/Breathe/demo6/particle.ts b/example/src/Examples/Breathe/demo6/particle.ts
new file mode 100644
index 0000000000..7ea7c888dd
--- /dev/null
+++ b/example/src/Examples/Breathe/demo6/particle.ts
@@ -0,0 +1,137 @@
+export const particleWGSL = `////////////////////////////////////////////////////////////////////////////////
+// Utilities
+////////////////////////////////////////////////////////////////////////////////
+var rand_seed : vec2f;
+
+fn init_rand(invocation_id : u32, seed : vec4f) {
+ rand_seed = seed.xz;
+ rand_seed = fract(rand_seed * cos(35.456+f32(invocation_id) * seed.yw));
+ rand_seed = fract(rand_seed * cos(41.235+f32(invocation_id) * seed.xw));
+}
+
+fn rand() -> f32 {
+ rand_seed.x = fract(cos(dot(rand_seed, vec2f(23.14077926, 232.61690225))) * 136.8168);
+ rand_seed.y = fract(cos(dot(rand_seed, vec2f(54.47856553, 345.84153136))) * 534.7645);
+ return rand_seed.y;
+}
+
+////////////////////////////////////////////////////////////////////////////////
+// Vertex shader
+////////////////////////////////////////////////////////////////////////////////
+struct RenderParams {
+ modelViewProjectionMatrix : mat4x4f,
+ right : vec3f,
+ up : vec3f
+}
+@binding(0) @group(0) var render_params : RenderParams;
+
+struct VertexInput {
+ @location(0) position : vec3f,
+ @location(1) color : vec4f,
+ @location(2) quad_pos : vec2f, // -1..+1
+}
+
+struct VertexOutput {
+ @builtin(position) position : vec4f,
+ @location(0) color : vec4f,
+ @location(1) quad_pos : vec2f, // -1..+1
+}
+
+@vertex
+fn vs_main(in : VertexInput) -> VertexOutput {
+ var quad_pos = mat2x3f(render_params.right, render_params.up) * in.quad_pos;
+ var position = in.position + quad_pos * 0.01;
+ var out : VertexOutput;
+ out.position = render_params.modelViewProjectionMatrix * vec4f(position, 1.0);
+ out.color = in.color;
+ out.quad_pos = in.quad_pos;
+ return out;
+}
+
+////////////////////////////////////////////////////////////////////////////////
+// Fragment shader
+////////////////////////////////////////////////////////////////////////////////
+@fragment
+fn fs_main(in : VertexOutput) -> @location(0) vec4f {
+ var color = in.color;
+ // Apply a circular particle alpha mask
+ color.a = color.a * max(1.0 - length(in.quad_pos), 0.0);
+ return color;
+}
+
+////////////////////////////////////////////////////////////////////////////////
+// Simulation Compute shader
+////////////////////////////////////////////////////////////////////////////////
+struct SimulationParams {
+ deltaTime : f32,
+ seed : vec4f,
+}
+
+struct Particle {
+ position : vec3f,
+ lifetime : f32,
+ color : vec4f,
+ velocity : vec3f,
+}
+
+struct Particles {
+ particles : array,
+}
+
+@binding(0) @group(0) var sim_params : SimulationParams;
+@binding(1) @group(0) var data : Particles;
+@binding(2) @group(0) var texture : texture_2d;
+
+@compute @workgroup_size(64)
+fn simulate(@builtin(global_invocation_id) global_invocation_id : vec3u) {
+ let idx = global_invocation_id.x;
+
+ init_rand(idx, sim_params.seed);
+
+ var particle = data.particles[idx];
+
+ // Apply gravity
+ particle.velocity.z = particle.velocity.z - sim_params.deltaTime * 0.5;
+
+ // Basic velocity integration
+ particle.position = particle.position + sim_params.deltaTime * particle.velocity;
+
+ // Age each particle. Fade out before vanishing.
+ particle.lifetime = particle.lifetime - sim_params.deltaTime;
+ particle.color.a = smoothstep(0.0, 0.5, particle.lifetime);
+
+ // If the lifetime has gone negative, then the particle is dead and should be
+ // respawned.
+ if (particle.lifetime < 0.0) {
+ // Use the probability map to find where the particle should be spawned.
+ // Starting with the 1x1 mip level.
+ var coord : vec2i;
+ for (var level = u32(textureNumLevels(texture) - 1); level > 0; level--) {
+ // Load the probability value from the mip-level
+ // Generate a random number and using the probabilty values, pick the
+ // next texel in the next largest mip level:
+ //
+ // 0.0 probabilites.r probabilites.g probabilites.b 1.0
+ // | | | | |
+ // | TOP-LEFT | TOP-RIGHT | BOTTOM-LEFT | BOTTOM_RIGHT |
+ //
+ let probabilites = textureLoad(texture, coord, level);
+ let value = vec4f(rand());
+ let mask = (value >= vec4f(0.0, probabilites.xyz)) & (value < probabilites);
+ coord = coord * 2;
+ coord.x = coord.x + select(0, 1, any(mask.yw)); // x y
+ coord.y = coord.y + select(0, 1, any(mask.zw)); // z w
+ }
+ let uv = vec2f(coord) / vec2f(textureDimensions(texture));
+ particle.position = vec3f((uv - 0.5) * 3.0 * vec2f(1.0, -1.0), 0.0);
+ particle.color = textureLoad(texture, coord, 0);
+ particle.velocity.x = (rand() - 0.5) * 0.1;
+ particle.velocity.y = (rand() - 0.5) * 0.1;
+ particle.velocity.z = rand() * 0.3;
+ particle.lifetime = 0.5 + rand() * 3.0;
+ }
+
+ // Store the new particle value
+ data.particles[idx] = particle;
+}
+`;
\ No newline at end of file
diff --git a/example/src/Examples/Breathe/demo6/probabilityMap.ts b/example/src/Examples/Breathe/demo6/probabilityMap.ts
new file mode 100644
index 0000000000..14493e5b17
--- /dev/null
+++ b/example/src/Examples/Breathe/demo6/probabilityMap.ts
@@ -0,0 +1,55 @@
+export const probabilityMapWGSL = `struct UBO {
+ width : u32,
+}
+
+struct Buffer {
+ weights : array,
+}
+
+@binding(0) @group(0) var ubo : UBO;
+@binding(1) @group(0) var buf_in : Buffer;
+@binding(2) @group(0) var buf_out : Buffer;
+@binding(3) @group(0) var tex_in : texture_2d;
+@binding(3) @group(0) var tex_out : texture_storage_2d;
+
+
+////////////////////////////////////////////////////////////////////////////////
+// import_level
+//
+// Loads the alpha channel from a texel of the source image, and writes it to
+// the buf_out.weights.
+////////////////////////////////////////////////////////////////////////////////
+@compute @workgroup_size(64)
+fn import_level(@builtin(global_invocation_id) coord : vec3u) {
+ _ = &buf_in;
+ let offset = coord.x + coord.y * ubo.width;
+ buf_out.weights[offset] = textureLoad(tex_in, vec2i(coord.xy), 0).w;
+}
+
+////////////////////////////////////////////////////////////////////////////////
+// export_level
+//
+// Loads 4 f32 weight values from buf_in.weights, and stores summed value into
+// buf_out.weights, along with the calculated 'probabilty' vec4 values into the
+// mip level of tex_out. See simulate() in particle.wgsl to understand the
+// probability logic.
+////////////////////////////////////////////////////////////////////////////////
+@compute @workgroup_size(64)
+fn export_level(@builtin(global_invocation_id) coord : vec3u) {
+ if (all(coord.xy < vec2u(textureDimensions(tex_out)))) {
+ let dst_offset = coord.x + coord.y * ubo.width;
+ let src_offset = coord.x*2u + coord.y*2u * ubo.width;
+
+ let a = buf_in.weights[src_offset + 0u];
+ let b = buf_in.weights[src_offset + 1u];
+ let c = buf_in.weights[src_offset + 0u + ubo.width];
+ let d = buf_in.weights[src_offset + 1u + ubo.width];
+ let sum = dot(vec4f(a, b, c, d), vec4f(1.0));
+
+ buf_out.weights[dst_offset] = sum / 4.0;
+
+ let probabilities = vec4f(a, a+b, a+b+c, sum) / max(sum, 0.0001);
+ textureStore(tex_out, vec2i(coord.xy), probabilities);
+ }
+}
+`;
\ No newline at end of file
diff --git a/example/src/Examples/Breathe/demo6/react.png b/example/src/Examples/Breathe/demo6/react.png
new file mode 100644
index 0000000000..06568a5233
Binary files /dev/null and b/example/src/Examples/Breathe/demo6/react.png differ
diff --git a/example/src/Examples/Breathe/demo6/test.png b/example/src/Examples/Breathe/demo6/test.png
new file mode 100644
index 0000000000..d19ce0a785
Binary files /dev/null and b/example/src/Examples/Breathe/demo6/test.png differ
diff --git a/example/src/Examples/Breathe/demo6/webgpu.png b/example/src/Examples/Breathe/demo6/webgpu.png
new file mode 100644
index 0000000000..a44b73ead9
Binary files /dev/null and b/example/src/Examples/Breathe/demo6/webgpu.png differ
diff --git a/package/.vscode/settings.json b/package/.vscode/settings.json
new file mode 100644
index 0000000000..9bc61e6971
--- /dev/null
+++ b/package/.vscode/settings.json
@@ -0,0 +1,69 @@
+{
+ "files.associations": {
+ "utility": "cpp",
+ "__bit_reference": "cpp",
+ "__config": "cpp",
+ "__hash_table": "cpp",
+ "__locale": "cpp",
+ "__node_handle": "cpp",
+ "__split_buffer": "cpp",
+ "__threading_support": "cpp",
+ "__tree": "cpp",
+ "__verbose_abort": "cpp",
+ "array": "cpp",
+ "bitset": "cpp",
+ "cctype": "cpp",
+ "cfenv": "cpp",
+ "charconv": "cpp",
+ "cinttypes": "cpp",
+ "clocale": "cpp",
+ "cmath": "cpp",
+ "codecvt": "cpp",
+ "complex": "cpp",
+ "condition_variable": "cpp",
+ "cstdarg": "cpp",
+ "cstddef": "cpp",
+ "cstdint": "cpp",
+ "cstdio": "cpp",
+ "cstdlib": "cpp",
+ "cstring": "cpp",
+ "ctime": "cpp",
+ "cwchar": "cpp",
+ "cwctype": "cpp",
+ "deque": "cpp",
+ "execution": "cpp",
+ "fstream": "cpp",
+ "initializer_list": "cpp",
+ "iomanip": "cpp",
+ "ios": "cpp",
+ "iosfwd": "cpp",
+ "iostream": "cpp",
+ "istream": "cpp",
+ "limits": "cpp",
+ "list": "cpp",
+ "locale": "cpp",
+ "map": "cpp",
+ "mutex": "cpp",
+ "new": "cpp",
+ "optional": "cpp",
+ "ostream": "cpp",
+ "queue": "cpp",
+ "ratio": "cpp",
+ "regex": "cpp",
+ "set": "cpp",
+ "shared_mutex": "cpp",
+ "sstream": "cpp",
+ "stack": "cpp",
+ "stdexcept": "cpp",
+ "streambuf": "cpp",
+ "string": "cpp",
+ "string_view": "cpp",
+ "tuple": "cpp",
+ "typeinfo": "cpp",
+ "unordered_map": "cpp",
+ "unordered_set": "cpp",
+ "variant": "cpp",
+ "vector": "cpp",
+ "algorithm": "cpp"
+ }
+}
\ No newline at end of file
diff --git a/package/android/CMakeLists.txt b/package/android/CMakeLists.txt
index 1c4b87ca6e..d475c79fd6 100644
--- a/package/android/CMakeLists.txt
+++ b/package/android/CMakeLists.txt
@@ -48,6 +48,7 @@ add_library(
"${PROJECT_SOURCE_DIR}/cpp/rnskia-android/SkiaOpenGLSurfaceFactory.cpp"
"${PROJECT_SOURCE_DIR}/cpp/rnskia-android/GrAHardwareBufferUtils.cpp"
"${PROJECT_SOURCE_DIR}/cpp/rnskia-android/WebGPUTriangle.cpp"
+ "${PROJECT_SOURCE_DIR}/cpp/rnskia-android/dawn/webgpu_cpp.cpp"
"${PROJECT_SOURCE_DIR}/../cpp/jsi/JsiHostObject.cpp"
"${PROJECT_SOURCE_DIR}/../cpp/jsi/JsiValue.cpp"
@@ -91,6 +92,8 @@ target_include_directories(
../cpp/wgpu
../cpp/jsi
../cpp/rnskia
+ ../cpp/rnskia/webgpu
+ ../cpp/rnskia/dawn
../cpp/rnskia/values
../cpp/rnskia/dom
../cpp/rnskia/dom/base
diff --git a/package/android/cpp/rnskia-android/RNSkAndroidPlatformContext.h b/package/android/cpp/rnskia-android/RNSkAndroidPlatformContext.h
index f0e505284d..4f30973cbb 100644
--- a/package/android/cpp/rnskia-android/RNSkAndroidPlatformContext.h
+++ b/package/android/cpp/rnskia-android/RNSkAndroidPlatformContext.h
@@ -27,6 +27,10 @@ class RNSkAndroidPlatformContext : public RNSkPlatformContext {
: RNSkPlatformContext(runtime, jsCallInvoker,
jniPlatformContext->getPixelDensity()),
_jniPlatformContext(jniPlatformContext) {
+ wgpu::InstanceDescriptor instanceDesc;
+ instanceDesc.features.timedWaitAnyEnable = true;
+ instanceDesc.features.timedWaitAnyMaxCount = 64;
+ _instance = wgpu::CreateInstance(&instanceDesc);
// Hook onto the notify draw loop callback in the platform context
jniPlatformContext->setOnNotifyDrawLoop(
[this]() { notifyDrawLoop(false); });
@@ -66,22 +70,20 @@ class RNSkAndroidPlatformContext : public RNSkPlatformContext {
void registerSurfaceDescriptor(int nativeId, void *window, int width,
int height) override {
- WGPUSurfaceDescriptorFromAndroidNativeWindow androidSurfaceDesc = {};
- androidSurfaceDesc.chain.sType =
- WGPUSType_SurfaceDescriptorFromAndroidNativeWindow;
- androidSurfaceDesc.window = window;
- WGPUSurfaceDescriptor surfaceDesc = {};
- surfaceDesc.nextInChain =
- reinterpret_cast(&androidSurfaceDesc);
+ wgpu::SurfaceDescriptorFromAndroidNativeWindow androidSurfaceDesc = {};
+ androidSurfaceDesc.window = window;
- wgpu::Instance instance = wgpuCreateInstance(nullptr);
- wgpu::Surface surface = wgpuInstanceCreateSurface(instance, &surfaceDesc);
+ wgpu::SurfaceDescriptor surfaceDesc = {};
+ surfaceDesc.nextInChain = &androidSurfaceDesc;
+ auto surface = _instance.CreateSurface(&surfaceDesc);
_descriptors[nativeId] = std::make_tuple(
std::make_shared(surface), width, height);
}
+ wgpu::Instance getInstance() { return _instance; }
+
virtual std::tuple, int, int>
getSurfaceDescriptor(int nativeId) override {
auto it = _descriptors.find(nativeId);
@@ -96,6 +98,7 @@ class RNSkAndroidPlatformContext : public RNSkPlatformContext {
JniPlatformContext *_jniPlatformContext;
std::map, int, int>>
_descriptors;
+ wgpu::Instance _instance = nullptr;
};
} // namespace RNSkia
diff --git a/package/android/cpp/rnskia-android/RNSkAndroidView.h b/package/android/cpp/rnskia-android/RNSkAndroidView.h
index 398138adf7..6926e83459 100644
--- a/package/android/cpp/rnskia-android/RNSkAndroidView.h
+++ b/package/android/cpp/rnskia-android/RNSkAndroidView.h
@@ -66,8 +66,9 @@ class RNSkAndroidView : public T, public RNSkBaseAndroidView {
auto nativeId = getSkiaView()->getNativeId();
T::getPlatformContext()->registerSurfaceDescriptor(nativeId, _window, width,
height);
-
- // runTriangleDemo(_window, width, height);
+ // RNSkLogger::logToConsole("Surface size changed: %d, %d",
+ // isVulkanSupported());
+ // runTriangleDemo(_window, width, height);
}
float getPixelDensity() override {
diff --git a/package/android/cpp/rnskia-android/WebGPUTriangle.cpp b/package/android/cpp/rnskia-android/WebGPUTriangle.cpp
index 6730384215..1f83d29a91 100644
--- a/package/android/cpp/rnskia-android/WebGPUTriangle.cpp
+++ b/package/android/cpp/rnskia-android/WebGPUTriangle.cpp
@@ -5,62 +5,84 @@
#include
#include
-#include "webgpu.hpp"
+#include "dawn/webgpu_cpp.h"
using namespace wgpu;
+namespace RNSkia {
+
void runTriangleDemo(void *window, int width, int height) {
RNSkia::RNSkLogger::logToConsole("width: %d, height: %d", width, height);
- Instance instance = wgpuCreateInstance(nullptr);
+ auto instance = CreateInstance(nullptr);
if (!instance) {
RNSkia::RNSkLogger::logToConsole("Failed to create WebGPU instance");
return;
}
- WGPUSurfaceDescriptorFromAndroidNativeWindow androidSurfaceDesc = {};
- androidSurfaceDesc.chain.sType =
- WGPUSType_SurfaceDescriptorFromAndroidNativeWindow;
+ SurfaceDescriptorFromAndroidNativeWindow androidSurfaceDesc = {};
androidSurfaceDesc.window = window;
// Set up the generic surface descriptor to use the platform-specific one
- WGPUSurfaceDescriptor surfaceDesc = {};
+ SurfaceDescriptor surfaceDesc = {};
surfaceDesc.nextInChain =
- reinterpret_cast(&androidSurfaceDesc);
- Surface surface = wgpuInstanceCreateSurface(instance, &surfaceDesc);
+ reinterpret_cast(&androidSurfaceDesc);
+ Surface surface = instance.CreateSurface(&surfaceDesc);
RNSkia::RNSkLogger::logToConsole("Requesting adapter...");
RequestAdapterOptions adapterOpts;
- // adapterOpts.compatibleSurface = surface;
- Adapter adapter = instance.requestAdapter(adapterOpts);
- std::cout << "Got adapter: " << adapter << std::endl;
- std::cout << "Requesting device..." << std::endl;
+ wgpu::Adapter adapter = nullptr;
+ instance.RequestAdapter(
+ nullptr,
+ [](WGPURequestAdapterStatus, WGPUAdapter cAdapter, const char *message,
+ void *userdata) {
+ if (message != nullptr) {
+ fprintf(stderr, "%s", message);
+ return;
+ }
+ *static_cast(userdata) =
+ wgpu::Adapter::Acquire(cAdapter);
+ },
+ &adapter);
+
+ wgpu::Device device = nullptr;
+ adapter.RequestDevice(
+ nullptr,
+ [](WGPURequestDeviceStatus, WGPUDevice cDevice, const char *message,
+ void *userdata) {
+ if (message != nullptr) {
+ fprintf(stderr, "%s", message);
+ return;
+ }
+ *static_cast(userdata) = wgpu::Device::Acquire(cDevice);
+ },
+ &device);
+
DeviceDescriptor deviceDesc;
deviceDesc.label = "My Device";
// deviceDesc.requiredFeaturesCount = 0;
deviceDesc.requiredLimits = nullptr;
deviceDesc.defaultQueue.label = "The default queue";
- Device device = adapter.requestDevice(deviceDesc);
- RNSkia::RNSkLogger::logToConsole("GOT DEVICE");
// Add an error callback for more debug info
- auto h = device.setUncapturedErrorCallback(
- [](ErrorType type, char const *message) {
- RNSkia::RNSkLogger::logToConsole("error: %s", message);
- });
-
- Queue queue = device.getQueue();
+ // auto h = device.SetUncapturedErrorCallback(
+ // [=](ErrorType type, char const *message, void *userData) {
+ // RNSkia::RNSkLogger::logToConsole("error: %s", message);
+ // RNSkia::RNSkLogger::logToConsole("GOT DEVICE");
+ // },
+ // nullptr);
+ Queue queue = device.GetQueue();
RNSkia::RNSkLogger::logToConsole("Creating swap chain...");
- TextureFormat swapChainFormat =
- surface.getPreferredFormat(adapter); // TextureFormat swapChainFormat =
- // TextureFormat::BGRA8Unorm;
+ // TextureFormat swapChainFormat = surface.GetPreferredFormat(
+ // adapter); // TextureFormat swapChainFormat =
+ // TextureFormat::BGRA8Unorm;
SwapChainDescriptor swapChainDesc;
swapChainDesc.width = width;
swapChainDesc.height = height;
swapChainDesc.usage = TextureUsage::RenderAttachment;
- swapChainDesc.format = swapChainFormat;
+ swapChainDesc.format = TextureFormat::RGBA8Unorm;
swapChainDesc.presentMode = PresentMode::Fifo;
- SwapChain swapChain = device.createSwapChain(surface, swapChainDesc);
+ SwapChain swapChain = device.CreateSwapChain(surface, &swapChainDesc);
RNSkia::RNSkLogger::logToConsole("Creating shader module.");
const char *shaderSource = R"(
@@ -89,15 +111,13 @@ fn fs_main() -> @location(0) vec4f {
// Use the extension mechanism to load a WGSL shader source code
ShaderModuleWGSLDescriptor shaderCodeDesc;
// Set the chained struct's header
- shaderCodeDesc.chain.next = nullptr;
- shaderCodeDesc.chain.sType = SType::ShaderModuleWGSLDescriptor;
// Connect the chain
- shaderDesc.nextInChain = &shaderCodeDesc.chain;
+ shaderDesc.nextInChain = &shaderCodeDesc;
// Setup the actual payload of the shader code descriptor
shaderCodeDesc.code = shaderSource;
- ShaderModule shaderModule = device.createShaderModule(shaderDesc);
+ auto shaderModule = device.CreateShaderModule(&shaderDesc);
RNSkia::RNSkLogger::logToConsole("Creating rendering pipeline.");
RenderPipelineDescriptor pipelineDesc;
@@ -115,8 +135,9 @@ fn fs_main() -> @location(0) vec4f {
// Primitive assembly and rasterization
// Each sequence of 3 vertices is considered as a triangle
pipelineDesc.primitive.topology = PrimitiveTopology::TriangleList;
- // We'll see later how to specify the order in which vertices should be
- // connected. When not specified, vertices are considered sequentially.
+ // We'll see later how to specify the order in which vertices should
+ // be connected. When not specified, vertices are considered
+ // sequentially.
pipelineDesc.primitive.stripIndexFormat = IndexFormat::Undefined;
// The face orientation is defined by assuming that when looking
// from the front of the face, its corner vertices are enumerated
@@ -147,13 +168,13 @@ fn fs_main() -> @location(0) vec4f {
blendState.alpha.operation = BlendOperation::Add;
ColorTargetState colorTarget;
- colorTarget.format = swapChainFormat;
+ colorTarget.format = TextureFormat::RGBA8Unorm;
colorTarget.blend = &blendState;
- colorTarget.writeMask =
- ColorWriteMask::All; // We could write to only some of the color channels.
+ colorTarget.writeMask = ColorWriteMask::All; // We could write to only some
+ // of the color channels.
- // We have only one target because our render pass has only one output color
- // attachment.
+ // We have only one target because our render pass has only one output
+ // color attachment.
fragmentState.targetCount = 1;
fragmentState.targets = &colorTarget;
@@ -171,21 +192,20 @@ fn fs_main() -> @location(0) vec4f {
// Pipeline layout
pipelineDesc.layout = nullptr;
- RenderPipeline pipeline = device.createRenderPipeline(pipelineDesc);
- std::cout << "Render pipeline: " << pipeline << std::endl;
+ RenderPipeline pipeline = device.CreateRenderPipeline(&pipelineDesc);
// while (true) {
// wgpuInstanceProcessEvents(instance);
- TextureView nextTexture = swapChain.getCurrentTextureView();
+ TextureView nextTexture = swapChain.GetCurrentTextureView();
if (!nextTexture) {
RNSkia::RNSkLogger::logToConsole("Cannot acquire next swap chain texture");
- return;
+ // return;
}
CommandEncoderDescriptor commandEncoderDesc;
commandEncoderDesc.label = "Command Encoder";
- CommandEncoder encoder = device.createCommandEncoder(commandEncoderDesc);
+ CommandEncoder encoder = device.CreateCommandEncoder(&commandEncoderDesc);
RenderPassDescriptor renderPassDesc;
@@ -202,38 +222,40 @@ fn fs_main() -> @location(0) vec4f {
renderPassDesc.depthStencilAttachment = nullptr;
// renderPassDesc.timestampWriteCount = 0;
renderPassDesc.timestampWrites = nullptr;
- RenderPassEncoder renderPass = encoder.beginRenderPass(renderPassDesc);
+ RenderPassEncoder renderPass = encoder.BeginRenderPass(&renderPassDesc);
// In its overall outline, drawing a triangle is as simple as this:
// Select which render pipeline to use
- renderPass.setPipeline(pipeline);
+ renderPass.SetPipeline(pipeline);
// Draw 1 instance of a 3-vertices shape
- renderPass.draw(3, 1, 0, 0);
-
- renderPass.end();
- renderPass.release();
+ renderPass.Draw(3, 1, 0, 0);
- nextTexture.release();
+ renderPass.End();
CommandBufferDescriptor cmdBufferDescriptor;
cmdBufferDescriptor.label = "Command buffer";
- CommandBuffer command = encoder.finish(cmdBufferDescriptor);
- encoder.release();
- std::vector commands;
+ CommandBuffer command = encoder.Finish(&cmdBufferDescriptor);
+ std::vector commands;
commands.push_back(command);
- queue.submit(command);
- command.release();
-
- swapChain.present();
- // }
-
- pipeline.release();
- shaderModule.release();
- swapChain.release();
- device.release();
- adapter.release();
- instance.release();
+ queue.Submit(commands.size(), commands.data());
+ bool done = false;
+ queue.OnSubmittedWorkDone(
+ [](WGPUQueueWorkDoneStatus status, void *userdata) {
+ RNSkia::RNSkLogger::logToConsole("Queue work done");
+ auto done = static_cast(userdata);
+ *done = true;
+ },
+ &done);
+ RNSkia::RNSkLogger::logToConsole("Preprocess events");
+ while (!done) {
+ instance.ProcessEvents();
+ }
+ RNSkia::RNSkLogger::logToConsole("Present");
+ swapChain.Present();
+
// surface.release();
// glfwDestroyWindow(window);
// glfwTerminate();
-}
\ No newline at end of file
+}
+
+} // namespace RNSkia
\ No newline at end of file
diff --git a/package/android/cpp/rnskia-android/WebGPUTriangle.h b/package/android/cpp/rnskia-android/WebGPUTriangle.h
index a29cc10965..0248532910 100644
--- a/package/android/cpp/rnskia-android/WebGPUTriangle.h
+++ b/package/android/cpp/rnskia-android/WebGPUTriangle.h
@@ -1,8 +1,14 @@
+#pragma once
+
#include
#include
#include
#define WEBGPU_CPP_IMPLEMENTATION
-void runTriangleDemo(void *surface, int width, int height);
\ No newline at end of file
+namespace RNSkia {
+
+void runTriangleDemo(void *surface, int width, int height);
+
+} // namespace RNSkia
\ No newline at end of file
diff --git a/package/android/cpp/rnskia-android/dawn/webgpu_cpp.cpp b/package/android/cpp/rnskia-android/dawn/webgpu_cpp.cpp
new file mode 100644
index 0000000000..b8784a52b5
--- /dev/null
+++ b/package/android/cpp/rnskia-android/dawn/webgpu_cpp.cpp
@@ -0,0 +1,6893 @@
+
+#include
+
+#include "dawn/webgpu_cpp.h"
+
+#if defined(__GNUC__) || defined(__clang__)
+// error: 'offsetof' within non-standard-layout type 'wgpu::XXX' is
+// conditionally-supported
+#pragma GCC diagnostic ignored "-Winvalid-offsetof"
+#endif
+
+namespace wgpu {
+
+// WGSLFeatureName
+
+static_assert(sizeof(WGSLFeatureName) == sizeof(WGPUWGSLFeatureName),
+ "sizeof mismatch for WGSLFeatureName");
+static_assert(alignof(WGSLFeatureName) == alignof(WGPUWGSLFeatureName),
+ "alignof mismatch for WGSLFeatureName");
+
+static_assert(static_cast(WGSLFeatureName::Undefined) ==
+ WGPUWGSLFeatureName_Undefined,
+ "value mismatch for WGSLFeatureName::Undefined");
+static_assert(
+ static_cast(
+ WGSLFeatureName::ReadonlyAndReadwriteStorageTextures) ==
+ WGPUWGSLFeatureName_ReadonlyAndReadwriteStorageTextures,
+ "value mismatch for WGSLFeatureName::ReadonlyAndReadwriteStorageTextures");
+static_assert(
+ static_cast(WGSLFeatureName::Packed4x8IntegerDotProduct) ==
+ WGPUWGSLFeatureName_Packed4x8IntegerDotProduct,
+ "value mismatch for WGSLFeatureName::Packed4x8IntegerDotProduct");
+static_assert(
+ static_cast(WGSLFeatureName::UnrestrictedPointerParameters) ==
+ WGPUWGSLFeatureName_UnrestrictedPointerParameters,
+ "value mismatch for WGSLFeatureName::UnrestrictedPointerParameters");
+static_assert(static_cast(WGSLFeatureName::PointerCompositeAccess) ==
+ WGPUWGSLFeatureName_PointerCompositeAccess,
+ "value mismatch for WGSLFeatureName::PointerCompositeAccess");
+static_assert(
+ static_cast(WGSLFeatureName::ChromiumTestingUnimplemented) ==
+ WGPUWGSLFeatureName_ChromiumTestingUnimplemented,
+ "value mismatch for WGSLFeatureName::ChromiumTestingUnimplemented");
+static_assert(
+ static_cast(WGSLFeatureName::ChromiumTestingUnsafeExperimental) ==
+ WGPUWGSLFeatureName_ChromiumTestingUnsafeExperimental,
+ "value mismatch for WGSLFeatureName::ChromiumTestingUnsafeExperimental");
+static_assert(
+ static_cast(WGSLFeatureName::ChromiumTestingExperimental) ==
+ WGPUWGSLFeatureName_ChromiumTestingExperimental,
+ "value mismatch for WGSLFeatureName::ChromiumTestingExperimental");
+static_assert(
+ static_cast(
+ WGSLFeatureName::ChromiumTestingShippedWithKillswitch) ==
+ WGPUWGSLFeatureName_ChromiumTestingShippedWithKillswitch,
+ "value mismatch for WGSLFeatureName::ChromiumTestingShippedWithKillswitch");
+static_assert(static_cast(WGSLFeatureName::ChromiumTestingShipped) ==
+ WGPUWGSLFeatureName_ChromiumTestingShipped,
+ "value mismatch for WGSLFeatureName::ChromiumTestingShipped");
+
+// AdapterType
+
+static_assert(sizeof(AdapterType) == sizeof(WGPUAdapterType),
+ "sizeof mismatch for AdapterType");
+static_assert(alignof(AdapterType) == alignof(WGPUAdapterType),
+ "alignof mismatch for AdapterType");
+
+static_assert(static_cast(AdapterType::DiscreteGPU) ==
+ WGPUAdapterType_DiscreteGPU,
+ "value mismatch for AdapterType::DiscreteGPU");
+static_assert(static_cast(AdapterType::IntegratedGPU) ==
+ WGPUAdapterType_IntegratedGPU,
+ "value mismatch for AdapterType::IntegratedGPU");
+static_assert(static_cast(AdapterType::CPU) == WGPUAdapterType_CPU,
+ "value mismatch for AdapterType::CPU");
+static_assert(static_cast(AdapterType::Unknown) ==
+ WGPUAdapterType_Unknown,
+ "value mismatch for AdapterType::Unknown");
+
+// AddressMode
+
+static_assert(sizeof(AddressMode) == sizeof(WGPUAddressMode),
+ "sizeof mismatch for AddressMode");
+static_assert(alignof(AddressMode) == alignof(WGPUAddressMode),
+ "alignof mismatch for AddressMode");
+
+static_assert(static_cast(AddressMode::Undefined) ==
+ WGPUAddressMode_Undefined,
+ "value mismatch for AddressMode::Undefined");
+static_assert(static_cast(AddressMode::ClampToEdge) ==
+ WGPUAddressMode_ClampToEdge,
+ "value mismatch for AddressMode::ClampToEdge");
+static_assert(static_cast(AddressMode::Repeat) ==
+ WGPUAddressMode_Repeat,
+ "value mismatch for AddressMode::Repeat");
+static_assert(static_cast(AddressMode::MirrorRepeat) ==
+ WGPUAddressMode_MirrorRepeat,
+ "value mismatch for AddressMode::MirrorRepeat");
+
+// AlphaMode
+
+static_assert(sizeof(AlphaMode) == sizeof(WGPUAlphaMode),
+ "sizeof mismatch for AlphaMode");
+static_assert(alignof(AlphaMode) == alignof(WGPUAlphaMode),
+ "alignof mismatch for AlphaMode");
+
+static_assert(static_cast(AlphaMode::Opaque) == WGPUAlphaMode_Opaque,
+ "value mismatch for AlphaMode::Opaque");
+static_assert(static_cast(AlphaMode::Premultiplied) ==
+ WGPUAlphaMode_Premultiplied,
+ "value mismatch for AlphaMode::Premultiplied");
+static_assert(static_cast(AlphaMode::Unpremultiplied) ==
+ WGPUAlphaMode_Unpremultiplied,
+ "value mismatch for AlphaMode::Unpremultiplied");
+
+// BackendType
+
+static_assert(sizeof(BackendType) == sizeof(WGPUBackendType),
+ "sizeof mismatch for BackendType");
+static_assert(alignof(BackendType) == alignof(WGPUBackendType),
+ "alignof mismatch for BackendType");
+
+static_assert(static_cast(BackendType::Undefined) ==
+ WGPUBackendType_Undefined,
+ "value mismatch for BackendType::Undefined");
+static_assert(static_cast(BackendType::Null) == WGPUBackendType_Null,
+ "value mismatch for BackendType::Null");
+static_assert(static_cast(BackendType::WebGPU) ==
+ WGPUBackendType_WebGPU,
+ "value mismatch for BackendType::WebGPU");
+static_assert(static_cast(BackendType::D3D11) ==
+ WGPUBackendType_D3D11,
+ "value mismatch for BackendType::D3D11");
+static_assert(static_cast(BackendType::D3D12) ==
+ WGPUBackendType_D3D12,
+ "value mismatch for BackendType::D3D12");
+static_assert(static_cast(BackendType::Metal) ==
+ WGPUBackendType_Metal,
+ "value mismatch for BackendType::Metal");
+static_assert(static_cast(BackendType::Vulkan) ==
+ WGPUBackendType_Vulkan,
+ "value mismatch for BackendType::Vulkan");
+static_assert(static_cast(BackendType::OpenGL) ==
+ WGPUBackendType_OpenGL,
+ "value mismatch for BackendType::OpenGL");
+static_assert(static_cast(BackendType::OpenGLES) ==
+ WGPUBackendType_OpenGLES,
+ "value mismatch for BackendType::OpenGLES");
+
+// BlendFactor
+
+static_assert(sizeof(BlendFactor) == sizeof(WGPUBlendFactor),
+ "sizeof mismatch for BlendFactor");
+static_assert(alignof(BlendFactor) == alignof(WGPUBlendFactor),
+ "alignof mismatch for BlendFactor");
+
+static_assert(static_cast(BlendFactor::Undefined) ==
+ WGPUBlendFactor_Undefined,
+ "value mismatch for BlendFactor::Undefined");
+static_assert(static_cast(BlendFactor::Zero) == WGPUBlendFactor_Zero,
+ "value mismatch for BlendFactor::Zero");
+static_assert(static_cast(BlendFactor::One) == WGPUBlendFactor_One,
+ "value mismatch for BlendFactor::One");
+static_assert(static_cast(BlendFactor::Src) == WGPUBlendFactor_Src,
+ "value mismatch for BlendFactor::Src");
+static_assert(static_cast(BlendFactor::OneMinusSrc) ==
+ WGPUBlendFactor_OneMinusSrc,
+ "value mismatch for BlendFactor::OneMinusSrc");
+static_assert(static_cast(BlendFactor::SrcAlpha) ==
+ WGPUBlendFactor_SrcAlpha,
+ "value mismatch for BlendFactor::SrcAlpha");
+static_assert(static_cast(BlendFactor::OneMinusSrcAlpha) ==
+ WGPUBlendFactor_OneMinusSrcAlpha,
+ "value mismatch for BlendFactor::OneMinusSrcAlpha");
+static_assert(static_cast(BlendFactor::Dst) == WGPUBlendFactor_Dst,
+ "value mismatch for BlendFactor::Dst");
+static_assert(static_cast(BlendFactor::OneMinusDst) ==
+ WGPUBlendFactor_OneMinusDst,
+ "value mismatch for BlendFactor::OneMinusDst");
+static_assert(static_cast(BlendFactor::DstAlpha) ==
+ WGPUBlendFactor_DstAlpha,
+ "value mismatch for BlendFactor::DstAlpha");
+static_assert(static_cast(BlendFactor::OneMinusDstAlpha) ==
+ WGPUBlendFactor_OneMinusDstAlpha,
+ "value mismatch for BlendFactor::OneMinusDstAlpha");
+static_assert(static_cast(BlendFactor::SrcAlphaSaturated) ==
+ WGPUBlendFactor_SrcAlphaSaturated,
+ "value mismatch for BlendFactor::SrcAlphaSaturated");
+static_assert(static_cast(BlendFactor::Constant) ==
+ WGPUBlendFactor_Constant,
+ "value mismatch for BlendFactor::Constant");
+static_assert(static_cast(BlendFactor::OneMinusConstant) ==
+ WGPUBlendFactor_OneMinusConstant,
+ "value mismatch for BlendFactor::OneMinusConstant");
+static_assert(static_cast(BlendFactor::Src1) == WGPUBlendFactor_Src1,
+ "value mismatch for BlendFactor::Src1");
+static_assert(static_cast(BlendFactor::OneMinusSrc1) ==
+ WGPUBlendFactor_OneMinusSrc1,
+ "value mismatch for BlendFactor::OneMinusSrc1");
+static_assert(static_cast(BlendFactor::Src1Alpha) ==
+ WGPUBlendFactor_Src1Alpha,
+ "value mismatch for BlendFactor::Src1Alpha");
+static_assert(static_cast(BlendFactor::OneMinusSrc1Alpha) ==
+ WGPUBlendFactor_OneMinusSrc1Alpha,
+ "value mismatch for BlendFactor::OneMinusSrc1Alpha");
+
+// BlendOperation
+
+static_assert(sizeof(BlendOperation) == sizeof(WGPUBlendOperation),
+ "sizeof mismatch for BlendOperation");
+static_assert(alignof(BlendOperation) == alignof(WGPUBlendOperation),
+ "alignof mismatch for BlendOperation");
+
+static_assert(static_cast(BlendOperation::Undefined) ==
+ WGPUBlendOperation_Undefined,
+ "value mismatch for BlendOperation::Undefined");
+static_assert(static_cast(BlendOperation::Add) ==
+ WGPUBlendOperation_Add,
+ "value mismatch for BlendOperation::Add");
+static_assert(static_cast(BlendOperation::Subtract) ==
+ WGPUBlendOperation_Subtract,
+ "value mismatch for BlendOperation::Subtract");
+static_assert(static_cast(BlendOperation::ReverseSubtract) ==
+ WGPUBlendOperation_ReverseSubtract,
+ "value mismatch for BlendOperation::ReverseSubtract");
+static_assert(static_cast(BlendOperation::Min) ==
+ WGPUBlendOperation_Min,
+ "value mismatch for BlendOperation::Min");
+static_assert(static_cast(BlendOperation::Max) ==
+ WGPUBlendOperation_Max,
+ "value mismatch for BlendOperation::Max");
+
+// BufferBindingType
+
+static_assert(sizeof(BufferBindingType) == sizeof(WGPUBufferBindingType),
+ "sizeof mismatch for BufferBindingType");
+static_assert(alignof(BufferBindingType) == alignof(WGPUBufferBindingType),
+ "alignof mismatch for BufferBindingType");
+
+static_assert(static_cast(BufferBindingType::Undefined) ==
+ WGPUBufferBindingType_Undefined,
+ "value mismatch for BufferBindingType::Undefined");
+static_assert(static_cast(BufferBindingType::Uniform) ==
+ WGPUBufferBindingType_Uniform,
+ "value mismatch for BufferBindingType::Uniform");
+static_assert(static_cast(BufferBindingType::Storage) ==
+ WGPUBufferBindingType_Storage,
+ "value mismatch for BufferBindingType::Storage");
+static_assert(static_cast(BufferBindingType::ReadOnlyStorage) ==
+ WGPUBufferBindingType_ReadOnlyStorage,
+ "value mismatch for BufferBindingType::ReadOnlyStorage");
+
+// BufferMapAsyncStatus
+
+static_assert(sizeof(BufferMapAsyncStatus) == sizeof(WGPUBufferMapAsyncStatus),
+ "sizeof mismatch for BufferMapAsyncStatus");
+static_assert(alignof(BufferMapAsyncStatus) ==
+ alignof(WGPUBufferMapAsyncStatus),
+ "alignof mismatch for BufferMapAsyncStatus");
+
+static_assert(static_cast(BufferMapAsyncStatus::Success) ==
+ WGPUBufferMapAsyncStatus_Success,
+ "value mismatch for BufferMapAsyncStatus::Success");
+static_assert(static_cast(BufferMapAsyncStatus::InstanceDropped) ==
+ WGPUBufferMapAsyncStatus_InstanceDropped,
+ "value mismatch for BufferMapAsyncStatus::InstanceDropped");
+static_assert(static_cast(BufferMapAsyncStatus::ValidationError) ==
+ WGPUBufferMapAsyncStatus_ValidationError,
+ "value mismatch for BufferMapAsyncStatus::ValidationError");
+static_assert(static_cast(BufferMapAsyncStatus::Unknown) ==
+ WGPUBufferMapAsyncStatus_Unknown,
+ "value mismatch for BufferMapAsyncStatus::Unknown");
+static_assert(static_cast(BufferMapAsyncStatus::DeviceLost) ==
+ WGPUBufferMapAsyncStatus_DeviceLost,
+ "value mismatch for BufferMapAsyncStatus::DeviceLost");
+static_assert(
+ static_cast(BufferMapAsyncStatus::DestroyedBeforeCallback) ==
+ WGPUBufferMapAsyncStatus_DestroyedBeforeCallback,
+ "value mismatch for BufferMapAsyncStatus::DestroyedBeforeCallback");
+static_assert(
+ static_cast(BufferMapAsyncStatus::UnmappedBeforeCallback) ==
+ WGPUBufferMapAsyncStatus_UnmappedBeforeCallback,
+ "value mismatch for BufferMapAsyncStatus::UnmappedBeforeCallback");
+static_assert(
+ static_cast(BufferMapAsyncStatus::MappingAlreadyPending) ==
+ WGPUBufferMapAsyncStatus_MappingAlreadyPending,
+ "value mismatch for BufferMapAsyncStatus::MappingAlreadyPending");
+static_assert(static_cast(BufferMapAsyncStatus::OffsetOutOfRange) ==
+ WGPUBufferMapAsyncStatus_OffsetOutOfRange,
+ "value mismatch for BufferMapAsyncStatus::OffsetOutOfRange");
+static_assert(static_cast(BufferMapAsyncStatus::SizeOutOfRange) ==
+ WGPUBufferMapAsyncStatus_SizeOutOfRange,
+ "value mismatch for BufferMapAsyncStatus::SizeOutOfRange");
+
+// BufferMapState
+
+static_assert(sizeof(BufferMapState) == sizeof(WGPUBufferMapState),
+ "sizeof mismatch for BufferMapState");
+static_assert(alignof(BufferMapState) == alignof(WGPUBufferMapState),
+ "alignof mismatch for BufferMapState");
+
+static_assert(static_cast(BufferMapState::Unmapped) ==
+ WGPUBufferMapState_Unmapped,
+ "value mismatch for BufferMapState::Unmapped");
+static_assert(static_cast(BufferMapState::Pending) ==
+ WGPUBufferMapState_Pending,
+ "value mismatch for BufferMapState::Pending");
+static_assert(static_cast(BufferMapState::Mapped) ==
+ WGPUBufferMapState_Mapped,
+ "value mismatch for BufferMapState::Mapped");
+
+// CallbackMode
+
+static_assert(sizeof(CallbackMode) == sizeof(WGPUCallbackMode),
+ "sizeof mismatch for CallbackMode");
+static_assert(alignof(CallbackMode) == alignof(WGPUCallbackMode),
+ "alignof mismatch for CallbackMode");
+
+static_assert(static_cast(CallbackMode::WaitAnyOnly) ==
+ WGPUCallbackMode_WaitAnyOnly,
+ "value mismatch for CallbackMode::WaitAnyOnly");
+static_assert(static_cast(CallbackMode::AllowProcessEvents) ==
+ WGPUCallbackMode_AllowProcessEvents,
+ "value mismatch for CallbackMode::AllowProcessEvents");
+static_assert(static_cast(CallbackMode::AllowSpontaneous) ==
+ WGPUCallbackMode_AllowSpontaneous,
+ "value mismatch for CallbackMode::AllowSpontaneous");
+
+// CompareFunction
+
+static_assert(sizeof(CompareFunction) == sizeof(WGPUCompareFunction),
+ "sizeof mismatch for CompareFunction");
+static_assert(alignof(CompareFunction) == alignof(WGPUCompareFunction),
+ "alignof mismatch for CompareFunction");
+
+static_assert(static_cast(CompareFunction::Undefined) ==
+ WGPUCompareFunction_Undefined,
+ "value mismatch for CompareFunction::Undefined");
+static_assert(static_cast(CompareFunction::Never) ==
+ WGPUCompareFunction_Never,
+ "value mismatch for CompareFunction::Never");
+static_assert(static_cast(CompareFunction::Less) ==
+ WGPUCompareFunction_Less,
+ "value mismatch for CompareFunction::Less");
+static_assert(static_cast(CompareFunction::Equal) ==
+ WGPUCompareFunction_Equal,
+ "value mismatch for CompareFunction::Equal");
+static_assert(static_cast(CompareFunction::LessEqual) ==
+ WGPUCompareFunction_LessEqual,
+ "value mismatch for CompareFunction::LessEqual");
+static_assert(static_cast(CompareFunction::Greater) ==
+ WGPUCompareFunction_Greater,
+ "value mismatch for CompareFunction::Greater");
+static_assert(static_cast(CompareFunction::NotEqual) ==
+ WGPUCompareFunction_NotEqual,
+ "value mismatch for CompareFunction::NotEqual");
+static_assert(static_cast(CompareFunction::GreaterEqual) ==
+ WGPUCompareFunction_GreaterEqual,
+ "value mismatch for CompareFunction::GreaterEqual");
+static_assert(static_cast(CompareFunction::Always) ==
+ WGPUCompareFunction_Always,
+ "value mismatch for CompareFunction::Always");
+
+// CompilationInfoRequestStatus
+
+static_assert(sizeof(CompilationInfoRequestStatus) ==
+ sizeof(WGPUCompilationInfoRequestStatus),
+ "sizeof mismatch for CompilationInfoRequestStatus");
+static_assert(alignof(CompilationInfoRequestStatus) ==
+ alignof(WGPUCompilationInfoRequestStatus),
+ "alignof mismatch for CompilationInfoRequestStatus");
+
+static_assert(static_cast(CompilationInfoRequestStatus::Success) ==
+ WGPUCompilationInfoRequestStatus_Success,
+ "value mismatch for CompilationInfoRequestStatus::Success");
+static_assert(
+ static_cast(CompilationInfoRequestStatus::InstanceDropped) ==
+ WGPUCompilationInfoRequestStatus_InstanceDropped,
+ "value mismatch for CompilationInfoRequestStatus::InstanceDropped");
+static_assert(static_cast(CompilationInfoRequestStatus::Error) ==
+ WGPUCompilationInfoRequestStatus_Error,
+ "value mismatch for CompilationInfoRequestStatus::Error");
+static_assert(static_cast(CompilationInfoRequestStatus::DeviceLost) ==
+ WGPUCompilationInfoRequestStatus_DeviceLost,
+ "value mismatch for CompilationInfoRequestStatus::DeviceLost");
+static_assert(static_cast(CompilationInfoRequestStatus::Unknown) ==
+ WGPUCompilationInfoRequestStatus_Unknown,
+ "value mismatch for CompilationInfoRequestStatus::Unknown");
+
+// CompilationMessageType
+
+static_assert(sizeof(CompilationMessageType) ==
+ sizeof(WGPUCompilationMessageType),
+ "sizeof mismatch for CompilationMessageType");
+static_assert(alignof(CompilationMessageType) ==
+ alignof(WGPUCompilationMessageType),
+ "alignof mismatch for CompilationMessageType");
+
+static_assert(static_cast(CompilationMessageType::Error) ==
+ WGPUCompilationMessageType_Error,
+ "value mismatch for CompilationMessageType::Error");
+static_assert(static_cast(CompilationMessageType::Warning) ==
+ WGPUCompilationMessageType_Warning,
+ "value mismatch for CompilationMessageType::Warning");
+static_assert(static_cast(CompilationMessageType::Info) ==
+ WGPUCompilationMessageType_Info,
+ "value mismatch for CompilationMessageType::Info");
+
+// CreatePipelineAsyncStatus
+
+static_assert(sizeof(CreatePipelineAsyncStatus) ==
+ sizeof(WGPUCreatePipelineAsyncStatus),
+ "sizeof mismatch for CreatePipelineAsyncStatus");
+static_assert(alignof(CreatePipelineAsyncStatus) ==
+ alignof(WGPUCreatePipelineAsyncStatus),
+ "alignof mismatch for CreatePipelineAsyncStatus");
+
+static_assert(static_cast(CreatePipelineAsyncStatus::Success) ==
+ WGPUCreatePipelineAsyncStatus_Success,
+ "value mismatch for CreatePipelineAsyncStatus::Success");
+static_assert(
+ static_cast(CreatePipelineAsyncStatus::InstanceDropped) ==
+ WGPUCreatePipelineAsyncStatus_InstanceDropped,
+ "value mismatch for CreatePipelineAsyncStatus::InstanceDropped");
+static_assert(
+ static_cast(CreatePipelineAsyncStatus::ValidationError) ==
+ WGPUCreatePipelineAsyncStatus_ValidationError,
+ "value mismatch for CreatePipelineAsyncStatus::ValidationError");
+static_assert(static_cast(CreatePipelineAsyncStatus::InternalError) ==
+ WGPUCreatePipelineAsyncStatus_InternalError,
+ "value mismatch for CreatePipelineAsyncStatus::InternalError");
+static_assert(static_cast(CreatePipelineAsyncStatus::DeviceLost) ==
+ WGPUCreatePipelineAsyncStatus_DeviceLost,
+ "value mismatch for CreatePipelineAsyncStatus::DeviceLost");
+static_assert(
+ static_cast(CreatePipelineAsyncStatus::DeviceDestroyed) ==
+ WGPUCreatePipelineAsyncStatus_DeviceDestroyed,
+ "value mismatch for CreatePipelineAsyncStatus::DeviceDestroyed");
+static_assert(static_cast(CreatePipelineAsyncStatus::Unknown) ==
+ WGPUCreatePipelineAsyncStatus_Unknown,
+ "value mismatch for CreatePipelineAsyncStatus::Unknown");
+
+// CullMode
+
+static_assert(sizeof(CullMode) == sizeof(WGPUCullMode),
+ "sizeof mismatch for CullMode");
+static_assert(alignof(CullMode) == alignof(WGPUCullMode),
+ "alignof mismatch for CullMode");
+
+static_assert(static_cast(CullMode::Undefined) ==
+ WGPUCullMode_Undefined,
+ "value mismatch for CullMode::Undefined");
+static_assert(static_cast(CullMode::None) == WGPUCullMode_None,
+ "value mismatch for CullMode::None");
+static_assert(static_cast(CullMode::Front) == WGPUCullMode_Front,
+ "value mismatch for CullMode::Front");
+static_assert(static_cast(CullMode::Back) == WGPUCullMode_Back,
+ "value mismatch for CullMode::Back");
+
+// DeviceLostReason
+
+static_assert(sizeof(DeviceLostReason) == sizeof(WGPUDeviceLostReason),
+ "sizeof mismatch for DeviceLostReason");
+static_assert(alignof(DeviceLostReason) == alignof(WGPUDeviceLostReason),
+ "alignof mismatch for DeviceLostReason");
+
+static_assert(static_cast(DeviceLostReason::Undefined) ==
+ WGPUDeviceLostReason_Undefined,
+ "value mismatch for DeviceLostReason::Undefined");
+static_assert(static_cast(DeviceLostReason::Destroyed) ==
+ WGPUDeviceLostReason_Destroyed,
+ "value mismatch for DeviceLostReason::Destroyed");
+
+// ErrorFilter
+
+static_assert(sizeof(ErrorFilter) == sizeof(WGPUErrorFilter),
+ "sizeof mismatch for ErrorFilter");
+static_assert(alignof(ErrorFilter) == alignof(WGPUErrorFilter),
+ "alignof mismatch for ErrorFilter");
+
+static_assert(static_cast(ErrorFilter::Validation) ==
+ WGPUErrorFilter_Validation,
+ "value mismatch for ErrorFilter::Validation");
+static_assert(static_cast(ErrorFilter::OutOfMemory) ==
+ WGPUErrorFilter_OutOfMemory,
+ "value mismatch for ErrorFilter::OutOfMemory");
+static_assert(static_cast(ErrorFilter::Internal) ==
+ WGPUErrorFilter_Internal,
+ "value mismatch for ErrorFilter::Internal");
+
+// ErrorType
+
+static_assert(sizeof(ErrorType) == sizeof(WGPUErrorType),
+ "sizeof mismatch for ErrorType");
+static_assert(alignof(ErrorType) == alignof(WGPUErrorType),
+ "alignof mismatch for ErrorType");
+
+static_assert(static_cast(ErrorType::NoError) ==
+ WGPUErrorType_NoError,
+ "value mismatch for ErrorType::NoError");
+static_assert(static_cast(ErrorType::Validation) ==
+ WGPUErrorType_Validation,
+ "value mismatch for ErrorType::Validation");
+static_assert(static_cast(ErrorType::OutOfMemory) ==
+ WGPUErrorType_OutOfMemory,
+ "value mismatch for ErrorType::OutOfMemory");
+static_assert(static_cast(ErrorType::Internal) ==
+ WGPUErrorType_Internal,
+ "value mismatch for ErrorType::Internal");
+static_assert(static_cast(ErrorType::Unknown) ==
+ WGPUErrorType_Unknown,
+ "value mismatch for ErrorType::Unknown");
+static_assert(static_cast(ErrorType::DeviceLost) ==
+ WGPUErrorType_DeviceLost,
+ "value mismatch for ErrorType::DeviceLost");
+
+// ExternalTextureRotation
+
+static_assert(sizeof(ExternalTextureRotation) ==
+ sizeof(WGPUExternalTextureRotation),
+ "sizeof mismatch for ExternalTextureRotation");
+static_assert(alignof(ExternalTextureRotation) ==
+ alignof(WGPUExternalTextureRotation),
+ "alignof mismatch for ExternalTextureRotation");
+
+static_assert(static_cast(ExternalTextureRotation::Rotate0Degrees) ==
+ WGPUExternalTextureRotation_Rotate0Degrees,
+ "value mismatch for ExternalTextureRotation::Rotate0Degrees");
+static_assert(static_cast(ExternalTextureRotation::Rotate90Degrees) ==
+ WGPUExternalTextureRotation_Rotate90Degrees,
+ "value mismatch for ExternalTextureRotation::Rotate90Degrees");
+static_assert(
+ static_cast(ExternalTextureRotation::Rotate180Degrees) ==
+ WGPUExternalTextureRotation_Rotate180Degrees,
+ "value mismatch for ExternalTextureRotation::Rotate180Degrees");
+static_assert(
+ static_cast(ExternalTextureRotation::Rotate270Degrees) ==
+ WGPUExternalTextureRotation_Rotate270Degrees,
+ "value mismatch for ExternalTextureRotation::Rotate270Degrees");
+
+// FeatureName
+
+static_assert(sizeof(FeatureName) == sizeof(WGPUFeatureName),
+ "sizeof mismatch for FeatureName");
+static_assert(alignof(FeatureName) == alignof(WGPUFeatureName),
+ "alignof mismatch for FeatureName");
+
+static_assert(static_cast(FeatureName::Undefined) ==
+ WGPUFeatureName_Undefined,
+ "value mismatch for FeatureName::Undefined");
+static_assert(static_cast(FeatureName::DepthClipControl) ==
+ WGPUFeatureName_DepthClipControl,
+ "value mismatch for FeatureName::DepthClipControl");
+static_assert(static_cast(FeatureName::Depth32FloatStencil8) ==
+ WGPUFeatureName_Depth32FloatStencil8,
+ "value mismatch for FeatureName::Depth32FloatStencil8");
+static_assert(static_cast(FeatureName::TimestampQuery) ==
+ WGPUFeatureName_TimestampQuery,
+ "value mismatch for FeatureName::TimestampQuery");
+static_assert(static_cast(FeatureName::TextureCompressionBC) ==
+ WGPUFeatureName_TextureCompressionBC,
+ "value mismatch for FeatureName::TextureCompressionBC");
+static_assert(static_cast(FeatureName::TextureCompressionETC2) ==
+ WGPUFeatureName_TextureCompressionETC2,
+ "value mismatch for FeatureName::TextureCompressionETC2");
+static_assert(static_cast(FeatureName::TextureCompressionASTC) ==
+ WGPUFeatureName_TextureCompressionASTC,
+ "value mismatch for FeatureName::TextureCompressionASTC");
+static_assert(static_cast(FeatureName::IndirectFirstInstance) ==
+ WGPUFeatureName_IndirectFirstInstance,
+ "value mismatch for FeatureName::IndirectFirstInstance");
+static_assert(static_cast(FeatureName::ShaderF16) ==
+ WGPUFeatureName_ShaderF16,
+ "value mismatch for FeatureName::ShaderF16");
+static_assert(static_cast(FeatureName::RG11B10UfloatRenderable) ==
+ WGPUFeatureName_RG11B10UfloatRenderable,
+ "value mismatch for FeatureName::RG11B10UfloatRenderable");
+static_assert(static_cast(FeatureName::BGRA8UnormStorage) ==
+ WGPUFeatureName_BGRA8UnormStorage,
+ "value mismatch for FeatureName::BGRA8UnormStorage");
+static_assert(static_cast(FeatureName::Float32Filterable) ==
+ WGPUFeatureName_Float32Filterable,
+ "value mismatch for FeatureName::Float32Filterable");
+static_assert(static_cast(FeatureName::DawnInternalUsages) ==
+ WGPUFeatureName_DawnInternalUsages,
+ "value mismatch for FeatureName::DawnInternalUsages");
+static_assert(static_cast(FeatureName::DawnMultiPlanarFormats) ==
+ WGPUFeatureName_DawnMultiPlanarFormats,
+ "value mismatch for FeatureName::DawnMultiPlanarFormats");
+static_assert(static_cast(FeatureName::DawnNative) ==
+ WGPUFeatureName_DawnNative,
+ "value mismatch for FeatureName::DawnNative");
+static_assert(
+ static_cast(
+ FeatureName::ChromiumExperimentalTimestampQueryInsidePasses) ==
+ WGPUFeatureName_ChromiumExperimentalTimestampQueryInsidePasses,
+ "value mismatch for "
+ "FeatureName::ChromiumExperimentalTimestampQueryInsidePasses");
+static_assert(
+ static_cast(FeatureName::ImplicitDeviceSynchronization) ==
+ WGPUFeatureName_ImplicitDeviceSynchronization,
+ "value mismatch for FeatureName::ImplicitDeviceSynchronization");
+static_assert(static_cast(FeatureName::SurfaceCapabilities) ==
+ WGPUFeatureName_SurfaceCapabilities,
+ "value mismatch for FeatureName::SurfaceCapabilities");
+static_assert(static_cast(FeatureName::TransientAttachments) ==
+ WGPUFeatureName_TransientAttachments,
+ "value mismatch for FeatureName::TransientAttachments");
+static_assert(static_cast(FeatureName::MSAARenderToSingleSampled) ==
+ WGPUFeatureName_MSAARenderToSingleSampled,
+ "value mismatch for FeatureName::MSAARenderToSingleSampled");
+static_assert(static_cast(FeatureName::DualSourceBlending) ==
+ WGPUFeatureName_DualSourceBlending,
+ "value mismatch for FeatureName::DualSourceBlending");
+static_assert(static_cast(FeatureName::D3D11MultithreadProtected) ==
+ WGPUFeatureName_D3D11MultithreadProtected,
+ "value mismatch for FeatureName::D3D11MultithreadProtected");
+static_assert(static_cast(FeatureName::ANGLETextureSharing) ==
+ WGPUFeatureName_ANGLETextureSharing,
+ "value mismatch for FeatureName::ANGLETextureSharing");
+static_assert(
+ static_cast(FeatureName::ChromiumExperimentalSubgroups) ==
+ WGPUFeatureName_ChromiumExperimentalSubgroups,
+ "value mismatch for FeatureName::ChromiumExperimentalSubgroups");
+static_assert(
+ static_cast(
+ FeatureName::ChromiumExperimentalSubgroupUniformControlFlow) ==
+ WGPUFeatureName_ChromiumExperimentalSubgroupUniformControlFlow,
+ "value mismatch for "
+ "FeatureName::ChromiumExperimentalSubgroupUniformControlFlow");
+static_assert(static_cast(FeatureName::PixelLocalStorageCoherent) ==
+ WGPUFeatureName_PixelLocalStorageCoherent,
+ "value mismatch for FeatureName::PixelLocalStorageCoherent");
+static_assert(
+ static_cast(FeatureName::PixelLocalStorageNonCoherent) ==
+ WGPUFeatureName_PixelLocalStorageNonCoherent,
+ "value mismatch for FeatureName::PixelLocalStorageNonCoherent");
+static_assert(static_cast(FeatureName::Unorm16TextureFormats) ==
+ WGPUFeatureName_Unorm16TextureFormats,
+ "value mismatch for FeatureName::Unorm16TextureFormats");
+static_assert(static_cast(FeatureName::Snorm16TextureFormats) ==
+ WGPUFeatureName_Snorm16TextureFormats,
+ "value mismatch for FeatureName::Snorm16TextureFormats");
+static_assert(
+ static_cast(FeatureName::MultiPlanarFormatExtendedUsages) ==
+ WGPUFeatureName_MultiPlanarFormatExtendedUsages,
+ "value mismatch for FeatureName::MultiPlanarFormatExtendedUsages");
+static_assert(static_cast(FeatureName::MultiPlanarFormatP010) ==
+ WGPUFeatureName_MultiPlanarFormatP010,
+ "value mismatch for FeatureName::MultiPlanarFormatP010");
+static_assert(static_cast(FeatureName::HostMappedPointer) ==
+ WGPUFeatureName_HostMappedPointer,
+ "value mismatch for FeatureName::HostMappedPointer");
+static_assert(static_cast(FeatureName::MultiPlanarRenderTargets) ==
+ WGPUFeatureName_MultiPlanarRenderTargets,
+ "value mismatch for FeatureName::MultiPlanarRenderTargets");
+static_assert(static_cast(FeatureName::MultiPlanarFormatNv12a) ==
+ WGPUFeatureName_MultiPlanarFormatNv12a,
+ "value mismatch for FeatureName::MultiPlanarFormatNv12a");
+static_assert(static_cast(FeatureName::FramebufferFetch) ==
+ WGPUFeatureName_FramebufferFetch,
+ "value mismatch for FeatureName::FramebufferFetch");
+static_assert(static_cast(FeatureName::BufferMapExtendedUsages) ==
+ WGPUFeatureName_BufferMapExtendedUsages,
+ "value mismatch for FeatureName::BufferMapExtendedUsages");
+static_assert(
+ static_cast(FeatureName::AdapterPropertiesMemoryHeaps) ==
+ WGPUFeatureName_AdapterPropertiesMemoryHeaps,
+ "value mismatch for FeatureName::AdapterPropertiesMemoryHeaps");
+static_assert(static_cast(FeatureName::AdapterPropertiesD3D) ==
+ WGPUFeatureName_AdapterPropertiesD3D,
+ "value mismatch for FeatureName::AdapterPropertiesD3D");
+static_assert(static_cast(FeatureName::AdapterPropertiesVk) ==
+ WGPUFeatureName_AdapterPropertiesVk,
+ "value mismatch for FeatureName::AdapterPropertiesVk");
+static_assert(static_cast(FeatureName::R8UnormStorage) ==
+ WGPUFeatureName_R8UnormStorage,
+ "value mismatch for FeatureName::R8UnormStorage");
+static_assert(static_cast(FeatureName::FormatCapabilities) ==
+ WGPUFeatureName_FormatCapabilities,
+ "value mismatch for FeatureName::FormatCapabilities");
+static_assert(static_cast(FeatureName::DrmFormatCapabilities) ==
+ WGPUFeatureName_DrmFormatCapabilities,
+ "value mismatch for FeatureName::DrmFormatCapabilities");
+static_assert(static_cast(FeatureName::Norm16TextureFormats) ==
+ WGPUFeatureName_Norm16TextureFormats,
+ "value mismatch for FeatureName::Norm16TextureFormats");
+static_assert(
+ static_cast(
+ FeatureName::SharedTextureMemoryVkDedicatedAllocation) ==
+ WGPUFeatureName_SharedTextureMemoryVkDedicatedAllocation,
+ "value mismatch for FeatureName::SharedTextureMemoryVkDedicatedAllocation");
+static_assert(
+ static_cast(FeatureName::SharedTextureMemoryAHardwareBuffer) ==
+ WGPUFeatureName_SharedTextureMemoryAHardwareBuffer,
+ "value mismatch for FeatureName::SharedTextureMemoryAHardwareBuffer");
+static_assert(static_cast(FeatureName::SharedTextureMemoryDmaBuf) ==
+ WGPUFeatureName_SharedTextureMemoryDmaBuf,
+ "value mismatch for FeatureName::SharedTextureMemoryDmaBuf");
+static_assert(static_cast(FeatureName::SharedTextureMemoryOpaqueFD) ==
+ WGPUFeatureName_SharedTextureMemoryOpaqueFD,
+ "value mismatch for FeatureName::SharedTextureMemoryOpaqueFD");
+static_assert(
+ static_cast(FeatureName::SharedTextureMemoryZirconHandle) ==
+ WGPUFeatureName_SharedTextureMemoryZirconHandle,
+ "value mismatch for FeatureName::SharedTextureMemoryZirconHandle");
+static_assert(
+ static_cast(FeatureName::SharedTextureMemoryDXGISharedHandle) ==
+ WGPUFeatureName_SharedTextureMemoryDXGISharedHandle,
+ "value mismatch for FeatureName::SharedTextureMemoryDXGISharedHandle");
+static_assert(
+ static_cast(FeatureName::SharedTextureMemoryD3D11Texture2D) ==
+ WGPUFeatureName_SharedTextureMemoryD3D11Texture2D,
+ "value mismatch for FeatureName::SharedTextureMemoryD3D11Texture2D");
+static_assert(
+ static_cast(FeatureName::SharedTextureMemoryIOSurface) ==
+ WGPUFeatureName_SharedTextureMemoryIOSurface,
+ "value mismatch for FeatureName::SharedTextureMemoryIOSurface");
+static_assert(static_cast(FeatureName::SharedTextureMemoryEGLImage) ==
+ WGPUFeatureName_SharedTextureMemoryEGLImage,
+ "value mismatch for FeatureName::SharedTextureMemoryEGLImage");
+static_assert(
+ static_cast(FeatureName::SharedFenceVkSemaphoreOpaqueFD) ==
+ WGPUFeatureName_SharedFenceVkSemaphoreOpaqueFD,
+ "value mismatch for FeatureName::SharedFenceVkSemaphoreOpaqueFD");
+static_assert(
+ static_cast(FeatureName::SharedFenceVkSemaphoreSyncFD) ==
+ WGPUFeatureName_SharedFenceVkSemaphoreSyncFD,
+ "value mismatch for FeatureName::SharedFenceVkSemaphoreSyncFD");
+static_assert(
+ static_cast(FeatureName::SharedFenceVkSemaphoreZirconHandle) ==
+ WGPUFeatureName_SharedFenceVkSemaphoreZirconHandle,
+ "value mismatch for FeatureName::SharedFenceVkSemaphoreZirconHandle");
+static_assert(static_cast(FeatureName::SharedFenceDXGISharedHandle) ==
+ WGPUFeatureName_SharedFenceDXGISharedHandle,
+ "value mismatch for FeatureName::SharedFenceDXGISharedHandle");
+static_assert(static_cast(FeatureName::SharedFenceMTLSharedEvent) ==
+ WGPUFeatureName_SharedFenceMTLSharedEvent,
+ "value mismatch for FeatureName::SharedFenceMTLSharedEvent");
+static_assert(
+ static_cast(FeatureName::SharedBufferMemoryD3D12Resource) ==
+ WGPUFeatureName_SharedBufferMemoryD3D12Resource,
+ "value mismatch for FeatureName::SharedBufferMemoryD3D12Resource");
+static_assert(static_cast(FeatureName::StaticSamplers) ==
+ WGPUFeatureName_StaticSamplers,
+ "value mismatch for FeatureName::StaticSamplers");
+
+// FilterMode
+
+static_assert(sizeof(FilterMode) == sizeof(WGPUFilterMode),
+ "sizeof mismatch for FilterMode");
+static_assert(alignof(FilterMode) == alignof(WGPUFilterMode),
+ "alignof mismatch for FilterMode");
+
+static_assert(static_cast(FilterMode::Undefined) ==
+ WGPUFilterMode_Undefined,
+ "value mismatch for FilterMode::Undefined");
+static_assert(static_cast(FilterMode::Nearest) ==
+ WGPUFilterMode_Nearest,
+ "value mismatch for FilterMode::Nearest");
+static_assert(static_cast(FilterMode::Linear) ==
+ WGPUFilterMode_Linear,
+ "value mismatch for FilterMode::Linear");
+
+// FrontFace
+
+static_assert(sizeof(FrontFace) == sizeof(WGPUFrontFace),
+ "sizeof mismatch for FrontFace");
+static_assert(alignof(FrontFace) == alignof(WGPUFrontFace),
+ "alignof mismatch for FrontFace");
+
+static_assert(static_cast(FrontFace::Undefined) ==
+ WGPUFrontFace_Undefined,
+ "value mismatch for FrontFace::Undefined");
+static_assert(static_cast(FrontFace::CCW) == WGPUFrontFace_CCW,
+ "value mismatch for FrontFace::CCW");
+static_assert(static_cast(FrontFace::CW) == WGPUFrontFace_CW,
+ "value mismatch for FrontFace::CW");
+
+// IndexFormat
+
+static_assert(sizeof(IndexFormat) == sizeof(WGPUIndexFormat),
+ "sizeof mismatch for IndexFormat");
+static_assert(alignof(IndexFormat) == alignof(WGPUIndexFormat),
+ "alignof mismatch for IndexFormat");
+
+static_assert(static_cast(IndexFormat::Undefined) ==
+ WGPUIndexFormat_Undefined,
+ "value mismatch for IndexFormat::Undefined");
+static_assert(static_cast(IndexFormat::Uint16) ==
+ WGPUIndexFormat_Uint16,
+ "value mismatch for IndexFormat::Uint16");
+static_assert(static_cast(IndexFormat::Uint32) ==
+ WGPUIndexFormat_Uint32,
+ "value mismatch for IndexFormat::Uint32");
+
+// LoadOp
+
+static_assert(sizeof(LoadOp) == sizeof(WGPULoadOp),
+ "sizeof mismatch for LoadOp");
+static_assert(alignof(LoadOp) == alignof(WGPULoadOp),
+ "alignof mismatch for LoadOp");
+
+static_assert(static_cast(LoadOp::Undefined) == WGPULoadOp_Undefined,
+ "value mismatch for LoadOp::Undefined");
+static_assert(static_cast(LoadOp::Clear) == WGPULoadOp_Clear,
+ "value mismatch for LoadOp::Clear");
+static_assert(static_cast(LoadOp::Load) == WGPULoadOp_Load,
+ "value mismatch for LoadOp::Load");
+
+// LoggingType
+
+static_assert(sizeof(LoggingType) == sizeof(WGPULoggingType),
+ "sizeof mismatch for LoggingType");
+static_assert(alignof(LoggingType) == alignof(WGPULoggingType),
+ "alignof mismatch for LoggingType");
+
+static_assert(static_cast(LoggingType::Verbose) ==
+ WGPULoggingType_Verbose,
+ "value mismatch for LoggingType::Verbose");
+static_assert(static_cast(LoggingType::Info) == WGPULoggingType_Info,
+ "value mismatch for LoggingType::Info");
+static_assert(static_cast(LoggingType::Warning) ==
+ WGPULoggingType_Warning,
+ "value mismatch for LoggingType::Warning");
+static_assert(static_cast(LoggingType::Error) ==
+ WGPULoggingType_Error,
+ "value mismatch for LoggingType::Error");
+
+// MipmapFilterMode
+
+static_assert(sizeof(MipmapFilterMode) == sizeof(WGPUMipmapFilterMode),
+ "sizeof mismatch for MipmapFilterMode");
+static_assert(alignof(MipmapFilterMode) == alignof(WGPUMipmapFilterMode),
+ "alignof mismatch for MipmapFilterMode");
+
+static_assert(static_cast(MipmapFilterMode::Undefined) ==
+ WGPUMipmapFilterMode_Undefined,
+ "value mismatch for MipmapFilterMode::Undefined");
+static_assert(static_cast(MipmapFilterMode::Nearest) ==
+ WGPUMipmapFilterMode_Nearest,
+ "value mismatch for MipmapFilterMode::Nearest");
+static_assert(static_cast(MipmapFilterMode::Linear) ==
+ WGPUMipmapFilterMode_Linear,
+ "value mismatch for MipmapFilterMode::Linear");
+
+// PopErrorScopeStatus
+
+static_assert(sizeof(PopErrorScopeStatus) == sizeof(WGPUPopErrorScopeStatus),
+ "sizeof mismatch for PopErrorScopeStatus");
+static_assert(alignof(PopErrorScopeStatus) == alignof(WGPUPopErrorScopeStatus),
+ "alignof mismatch for PopErrorScopeStatus");
+
+static_assert(static_cast(PopErrorScopeStatus::Success) ==
+ WGPUPopErrorScopeStatus_Success,
+ "value mismatch for PopErrorScopeStatus::Success");
+static_assert(static_cast(PopErrorScopeStatus::InstanceDropped) ==
+ WGPUPopErrorScopeStatus_InstanceDropped,
+ "value mismatch for PopErrorScopeStatus::InstanceDropped");
+
+// PowerPreference
+
+static_assert(sizeof(PowerPreference) == sizeof(WGPUPowerPreference),
+ "sizeof mismatch for PowerPreference");
+static_assert(alignof(PowerPreference) == alignof(WGPUPowerPreference),
+ "alignof mismatch for PowerPreference");
+
+static_assert(static_cast(PowerPreference::Undefined) ==
+ WGPUPowerPreference_Undefined,
+ "value mismatch for PowerPreference::Undefined");
+static_assert(static_cast(PowerPreference::LowPower) ==
+ WGPUPowerPreference_LowPower,
+ "value mismatch for PowerPreference::LowPower");
+static_assert(static_cast(PowerPreference::HighPerformance) ==
+ WGPUPowerPreference_HighPerformance,
+ "value mismatch for PowerPreference::HighPerformance");
+
+// PresentMode
+
+static_assert(sizeof(PresentMode) == sizeof(WGPUPresentMode),
+ "sizeof mismatch for PresentMode");
+static_assert(alignof(PresentMode) == alignof(WGPUPresentMode),
+ "alignof mismatch for PresentMode");
+
+static_assert(static_cast(PresentMode::Fifo) == WGPUPresentMode_Fifo,
+ "value mismatch for PresentMode::Fifo");
+static_assert(static_cast(PresentMode::Immediate) ==
+ WGPUPresentMode_Immediate,
+ "value mismatch for PresentMode::Immediate");
+static_assert(static_cast(PresentMode::Mailbox) ==
+ WGPUPresentMode_Mailbox,
+ "value mismatch for PresentMode::Mailbox");
+
+// PrimitiveTopology
+
+static_assert(sizeof(PrimitiveTopology) == sizeof(WGPUPrimitiveTopology),
+ "sizeof mismatch for PrimitiveTopology");
+static_assert(alignof(PrimitiveTopology) == alignof(WGPUPrimitiveTopology),
+ "alignof mismatch for PrimitiveTopology");
+
+static_assert(static_cast(PrimitiveTopology::Undefined) ==
+ WGPUPrimitiveTopology_Undefined,
+ "value mismatch for PrimitiveTopology::Undefined");
+static_assert(static_cast(PrimitiveTopology::PointList) ==
+ WGPUPrimitiveTopology_PointList,
+ "value mismatch for PrimitiveTopology::PointList");
+static_assert(static_cast(PrimitiveTopology::LineList) ==
+ WGPUPrimitiveTopology_LineList,
+ "value mismatch for PrimitiveTopology::LineList");
+static_assert(static_cast(PrimitiveTopology::LineStrip) ==
+ WGPUPrimitiveTopology_LineStrip,
+ "value mismatch for PrimitiveTopology::LineStrip");
+static_assert(static_cast(PrimitiveTopology::TriangleList) ==
+ WGPUPrimitiveTopology_TriangleList,
+ "value mismatch for PrimitiveTopology::TriangleList");
+static_assert(static_cast