diff --git a/example/package.json b/example/package.json index 3824be359b..5f4ef5634b 100644 --- a/example/package.json +++ b/example/package.json @@ -35,7 +35,8 @@ "react-native-safe-area-context": "4.3.4", "react-native-screens": "3.17.0", "react-native-svg": "13.8.0", - "react-native-web": "0.18.0" + "react-native-web": "0.18.0", + "wgpu-matrix": "^2.8.0" }, "devDependencies": { "@babel/core": "7.20.12", diff --git a/example/src/Examples/Breathe/Breathe.tsx b/example/src/Examples/Breathe/Breathe.tsx index 65a1db9a33..70ee72aa67 100644 --- a/example/src/Examples/Breathe/Breathe.tsx +++ b/example/src/Examples/Breathe/Breathe.tsx @@ -3,6 +3,7 @@ import { gpu, SkiaDomView, } from "@shopify/react-native-skia"; +import { demo1 } from "./demo1/main"; const triangleVertWGSL = `@vertex fn main( @@ -24,64 +25,7 @@ fn main() -> @location(0) vec4f { }`; const draw = async (ctx: GPUCanvasContext) => { - const adapter = await gpu.requestAdapter(); - const device = await adapter!.requestDevice(); - - const presentationFormat = gpu.getPreferredCanvasFormat(); - ctx.configure({ - device, - format: "bgra8unorm" - }); - - const vertex: GPUVertexState = { - entryPoint: "main", - module: device.createShaderModule({ - code: triangleVertWGSL, - }), - }; - - const fragment: GPUFragmentState = { - entryPoint: "main", - module: device.createShaderModule({ - code: redFragWGSL, - }), - targets: [ - { - format: presentationFormat, - }, - ], - }; - - // const pipelineOld = device.createRenderPipeline({ - // layout: "auto", - // vertex, - // fragment, - // primitive: { - // topology: "triangle-list", - // }, - // }); - - const commandEncoder = device.createCommandEncoder(); - - const pipeline = ctx.runDemo(device, null, commandEncoder, vertex, fragment); - const textureView = ctx.getCurrentTexture().createView(); - const renderPassDescriptor: GPURenderPassDescriptor = { - colorAttachments: [ - { - view: textureView, - clearValue: [1.0, 0.0, 1, 1], - loadOp: 'clear', - storeOp: 'store', - }, - ], - }; - - - const passEncoder = commandEncoder.beginRenderPass(renderPassDescriptor); - passEncoder.setPipeline(pipeline); - passEncoder.draw(3); - passEncoder.end(); - device.queue.submit([commandEncoder.finish()]); + await demo1(ctx); ctx.present(); }; diff --git a/example/src/Examples/Breathe/demo1/cube.ts b/example/src/Examples/Breathe/demo1/cube.ts new file mode 100644 index 0000000000..f80c705e57 --- /dev/null +++ b/example/src/Examples/Breathe/demo1/cube.ts @@ -0,0 +1,51 @@ +export const cubeVertexSize = 4 * 10; // Byte size of one cube vertex. +export const cubePositionOffset = 0; +export const cubeColorOffset = 4 * 4; // Byte offset of cube vertex color attribute. +export const cubeUVOffset = 4 * 8; +export const cubeVertexCount = 36; + +// prettier-ignore +export const cubeVertexArray = new Float32Array([ + // float4 position, float4 color, float2 uv, + 1, -1, 1, 1, 1, 0, 1, 1, 0, 1, + -1, -1, 1, 1, 0, 0, 1, 1, 1, 1, + -1, -1, -1, 1, 0, 0, 0, 1, 1, 0, + 1, -1, -1, 1, 1, 0, 0, 1, 0, 0, + 1, -1, 1, 1, 1, 0, 1, 1, 0, 1, + -1, -1, -1, 1, 0, 0, 0, 1, 1, 0, + + 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, + 1, -1, 1, 1, 1, 0, 1, 1, 1, 1, + 1, -1, -1, 1, 1, 0, 0, 1, 1, 0, + 1, 1, -1, 1, 1, 1, 0, 1, 0, 0, + 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, + 1, -1, -1, 1, 1, 0, 0, 1, 1, 0, + + -1, 1, 1, 1, 0, 1, 1, 1, 0, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, -1, 1, 1, 1, 0, 1, 1, 0, + -1, 1, -1, 1, 0, 1, 0, 1, 0, 0, + -1, 1, 1, 1, 0, 1, 1, 1, 0, 1, + 1, 1, -1, 1, 1, 1, 0, 1, 1, 0, + + -1, -1, 1, 1, 0, 0, 1, 1, 0, 1, + -1, 1, 1, 1, 0, 1, 1, 1, 1, 1, + -1, 1, -1, 1, 0, 1, 0, 1, 1, 0, + -1, -1, -1, 1, 0, 0, 0, 1, 0, 0, + -1, -1, 1, 1, 0, 0, 1, 1, 0, 1, + -1, 1, -1, 1, 0, 1, 0, 1, 1, 0, + + 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, + -1, 1, 1, 1, 0, 1, 1, 1, 1, 1, + -1, -1, 1, 1, 0, 0, 1, 1, 1, 0, + -1, -1, 1, 1, 0, 0, 1, 1, 1, 0, + 1, -1, 1, 1, 1, 0, 1, 1, 0, 0, + 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, + + 1, -1, -1, 1, 1, 0, 0, 1, 0, 1, + -1, -1, -1, 1, 0, 0, 0, 1, 1, 1, + -1, 1, -1, 1, 0, 1, 0, 1, 1, 0, + 1, 1, -1, 1, 1, 1, 0, 1, 0, 0, + 1, -1, -1, 1, 1, 0, 0, 1, 0, 1, + -1, 1, -1, 1, 0, 1, 0, 1, 1, 0, +]); \ No newline at end of file diff --git a/example/src/Examples/Breathe/demo1/main.ts b/example/src/Examples/Breathe/demo1/main.ts new file mode 100644 index 0000000000..e53d1ee12f --- /dev/null +++ b/example/src/Examples/Breathe/demo1/main.ts @@ -0,0 +1,210 @@ +import { mat4, vec3 } from 'wgpu-matrix'; + +import { + cubeVertexArray, + cubeVertexSize, + 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: [ + { + 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, + 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), + 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()]); + + 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 new file mode 100644 index 0000000000..ee8ad26a64 --- /dev/null +++ b/example/src/Examples/Breathe/demo1/shaders.ts @@ -0,0 +1,30 @@ +export const vertexPositionColorWGSL = `@fragment +fn main( + @location(0) fragUV: vec2f, + @location(1) fragPosition: vec4f +) -> @location(0) vec4f { + return fragPosition; +}`; + +export const basicVertWGSL = `struct Uniforms { + modelViewProjectionMatrix : mat4x4f, +} +@binding(0) @group(0) var uniforms : Uniforms; + +struct VertexOutput { + @builtin(position) Position : vec4f, + @location(0) fragUV : vec2f, + @location(1) fragPosition: vec4f, +} + +@vertex +fn main( + @location(0) position : vec4f, + @location(1) uv : vec2f +) -> VertexOutput { + var output : VertexOutput; + output.Position = uniforms.modelViewProjectionMatrix * position; + 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 diff --git a/example/yarn.lock b/example/yarn.lock index afadf2d56d..01823e67fc 100644 --- a/example/yarn.lock +++ b/example/yarn.lock @@ -2978,9 +2978,7 @@ "@shopify/react-native-skia@link:../package": version "0.0.0" - dependencies: - canvaskit-wasm "0.39.1" - react-reconciler "0.27.0" + uid "" "@sideway/address@^4.1.3": version "4.1.4" @@ -10984,6 +10982,11 @@ websocket-extensions@>=0.1.1: resolved "https://registry.yarnpkg.com/websocket-extensions/-/websocket-extensions-0.1.4.tgz#7f8473bc839dfd87608adb95d7eb075211578a42" integrity sha512-OqedPIGOfsDlo31UNwYbCFMSaO9m9G/0faIHj5/dZFDMFqPTcx6UwqyOy3COEaEOg/9VsGIpdqn62W5KhoKSpg== +wgpu-matrix@^2.8.0: + version "2.8.0" + resolved "https://registry.yarnpkg.com/wgpu-matrix/-/wgpu-matrix-2.8.0.tgz#a0416867fc413f6e51340ba0ac5f95b85f841990" + integrity sha512-HSuLmWpr1b1kdBbOYsAZodGmIQjD42Or6vjL39hAAo19E07sgBDAII4rGuP4qr4hsfTsA3OhDJPqMTQ0XLpH9Q== + whatwg-fetch@^3.0.0: version "3.6.2" resolved "https://registry.yarnpkg.com/whatwg-fetch/-/whatwg-fetch-3.6.2.tgz#dced24f37f2624ed0281725d51d0e2e3fe677f8c" diff --git a/package/cpp/wgpu/JsiAdapter.h b/package/cpp/wgpu/JsiAdapter.h index 98ecdaab9d..4698cbf816 100644 --- a/package/cpp/wgpu/JsiAdapter.h +++ b/package/cpp/wgpu/JsiAdapter.h @@ -27,7 +27,7 @@ class JsiAdapter : public JsiSkWrappingSharedPtrHostObject { context, std::make_shared(std::move(m))) {} JSI_HOST_FUNCTION(requestDevice) { - auto defaultDescriptor = std::make_shared(); + auto defaultDescriptor = new wgpu::DeviceDescriptor(); auto descriptor = count > 0 ? JsiDeviceDescriptor::fromValue(runtime, arguments[0]) : defaultDescriptor; @@ -39,7 +39,7 @@ class JsiAdapter : public JsiSkWrappingSharedPtrHostObject { descriptor = std::move(descriptor)]( jsi::Runtime &runtime, std::shared_ptr promise) -> void { - auto ret = object->requestDevice(*descriptor.get()); + auto ret = object->requestDevice(*descriptor); if (ret == nullptr) { promise->resolve(jsi::Value::null()); } else { @@ -58,11 +58,11 @@ class JsiAdapter : public JsiSkWrappingSharedPtrHostObject { /** * Returns the underlying object from a host object of this type */ - static std::shared_ptr fromValue(jsi::Runtime &runtime, - const jsi::Value &raw) { + static wgpu::Adapter *fromValue(jsi::Runtime &runtime, + const jsi::Value &raw) { const auto &obj = raw.asObject(runtime); if (obj.isHostObject(runtime)) { - return obj.asHostObject(runtime)->getObject(); + return obj.asHostObject(runtime)->getObject().get(); } else { throw jsi::JSError(runtime, "Expected a JsiAdapter object, but got a " + raw.toString(runtime).utf8(runtime)); diff --git a/package/cpp/wgpu/JsiBindGroup.h b/package/cpp/wgpu/JsiBindGroup.h new file mode 100644 index 0000000000..cb89b788df --- /dev/null +++ b/package/cpp/wgpu/JsiBindGroup.h @@ -0,0 +1,44 @@ +#pragma once +#include +#include +#include + +#include "webgpu.hpp" + +#include + +#include "JsiEnums.h" +#include "JsiHostObject.h" +#include "JsiPromises.h" +#include "JsiSkHostObjects.h" +#include "RNSkLog.h" +#include "RNSkPlatformContext.h" + +namespace RNSkia { + +namespace jsi = facebook::jsi; + +class JsiBindGroup : public JsiSkWrappingSharedPtrHostObject { +public: + JsiBindGroup(std::shared_ptr context, wgpu::BindGroup m) + : JsiSkWrappingSharedPtrHostObject( + context, std::make_shared(std::move(m))) {} + + // TODO: this fix, use JSI_EXPORT_PROPERTY_GETTERS instead + EXPORT_JSI_API_BRANDNAME(JsiBindGroup, BindGroup) + + /** + * Returns the underlying object from a host object of this type + */ + static wgpu::BindGroup *fromValue(jsi::Runtime &runtime, + const jsi::Value &raw) { + const auto &obj = raw.asObject(runtime); + if (obj.isHostObject(runtime)) { + return obj.asHostObject(runtime)->getObject().get(); + } else { + throw jsi::JSError(runtime, "Expected a JsiBindGroup object, but got a " + + raw.toString(runtime).utf8(runtime)); + } + } +}; +} // namespace RNSkia diff --git a/package/cpp/wgpu/JsiBindGroupDescriptor.h b/package/cpp/wgpu/JsiBindGroupDescriptor.h new file mode 100644 index 0000000000..7c1e1cd419 --- /dev/null +++ b/package/cpp/wgpu/JsiBindGroupDescriptor.h @@ -0,0 +1,79 @@ +#pragma once +#include +#include +#include + +#include "webgpu.hpp" + +#include + +#include "JsiBindGroupEntry.h" +#include "JsiBindGroupLayout.h" +#include "JsiEnums.h" +#include "JsiHostObject.h" +#include "JsiPromises.h" +#include "JsiSkHostObjects.h" +#include "RNSkLog.h" +#include "RNSkPlatformContext.h" + +namespace RNSkia { + +namespace jsi = facebook::jsi; + +class JsiBindGroupDescriptor + : public JsiSkWrappingSharedPtrHostObject { +public: + JsiBindGroupDescriptor(std::shared_ptr context, + wgpu::BindGroupDescriptor m) + : JsiSkWrappingSharedPtrHostObject( + context, + std::make_shared(std::move(m))) {} + + // TODO: this fix, use JSI_EXPORT_PROPERTY_GETTERS instead + EXPORT_JSI_API_BRANDNAME(JsiBindGroupDescriptor, BindGroupDescriptor) + + /** + * Returns the underlying object from a host object of this type + */ + static wgpu::BindGroupDescriptor *fromValue(jsi::Runtime &runtime, + const jsi::Value &raw) { + const auto &obj = raw.asObject(runtime); + if (obj.isHostObject(runtime)) { + return obj.asHostObject(runtime) + ->getObject() + .get(); + } else { + auto object = new wgpu::BindGroupDescriptor(); + object->setDefault(); + + if (obj.hasProperty(runtime, "layout")) { + auto layout = obj.getProperty(runtime, "layout"); + + object->layout = *JsiBindGroupLayout::fromValue(runtime, layout); + } else { + throw jsi::JSError( + runtime, "Missing mandatory prop layout in BindGroupDescriptor"); + } + if (obj.hasProperty(runtime, "entries")) { + auto entries = obj.getProperty(runtime, "entries"); + auto jsiArray1 = entries.asObject(runtime).asArray(runtime); + auto jsiArray1Size = static_cast(jsiArray1.size(runtime)); + auto array1 = new std::vector(); + array1->reserve(jsiArray1Size); + for (int i = 0; i < jsiArray1Size; i++) { + auto element = JsiBindGroupEntry::fromValue( + runtime, jsiArray1.getValueAtIndex(runtime, i)); + array1->push_back(*element); + } + + object->entryCount = jsiArray1Size; + object->entries = array1->data(); + } else { + throw jsi::JSError( + runtime, "Missing mandatory prop entries in BindGroupDescriptor"); + } + return object; + } + } +}; +} // namespace RNSkia diff --git a/package/cpp/wgpu/JsiBindGroupEntry.h b/package/cpp/wgpu/JsiBindGroupEntry.h new file mode 100644 index 0000000000..cfe822a5fa --- /dev/null +++ b/package/cpp/wgpu/JsiBindGroupEntry.h @@ -0,0 +1,65 @@ +#pragma once +#include +#include +#include + +#include "webgpu.hpp" + +#include + +#include "JsiBuffer.h" +#include "JsiEnums.h" +#include "JsiHostObject.h" +#include "JsiPromises.h" +#include "JsiSkHostObjects.h" +#include "RNSkLog.h" +#include "RNSkPlatformContext.h" + +namespace RNSkia { + +namespace jsi = facebook::jsi; + +class JsiBindGroupEntry + : public JsiSkWrappingSharedPtrHostObject { +public: + JsiBindGroupEntry(std::shared_ptr context, + wgpu::BindGroupEntry m) + : JsiSkWrappingSharedPtrHostObject( + context, std::make_shared(std::move(m))) {} + + // TODO: this fix, use JSI_EXPORT_PROPERTY_GETTERS instead + EXPORT_JSI_API_BRANDNAME(JsiBindGroupEntry, BindGroupEntry) + + /** + * Returns the underlying object from a host object of this type + */ + static wgpu::BindGroupEntry *fromValue(jsi::Runtime &runtime, + const jsi::Value &raw) { + const auto &obj = raw.asObject(runtime); + if (obj.isHostObject(runtime)) { + return obj.asHostObject(runtime)->getObject().get(); + } else { + auto object = new wgpu::BindGroupEntry(); + object->setDefault(); + + if (obj.hasProperty(runtime, "binding")) { + auto binding = obj.getProperty(runtime, "binding"); + + object->binding = static_cast(binding.getNumber()); + } else { + throw jsi::JSError(runtime, + "Missing mandatory prop binding in BindGroupEntry"); + } + if (obj.hasProperty(runtime, "buffer")) { + auto buffer = obj.getProperty(runtime, "buffer"); + + object->buffer = *JsiBuffer::fromValue(runtime, buffer); + } else { + throw jsi::JSError(runtime, + "Missing mandatory prop buffer in BindGroupEntry"); + } + return object; + } + } +}; +} // namespace RNSkia diff --git a/package/cpp/wgpu/JsiBindGroupLayout.h b/package/cpp/wgpu/JsiBindGroupLayout.h new file mode 100644 index 0000000000..b3a4fbee6d --- /dev/null +++ b/package/cpp/wgpu/JsiBindGroupLayout.h @@ -0,0 +1,47 @@ +#pragma once +#include +#include +#include + +#include "webgpu.hpp" + +#include + +#include "JsiEnums.h" +#include "JsiHostObject.h" +#include "JsiPromises.h" +#include "JsiSkHostObjects.h" +#include "RNSkLog.h" +#include "RNSkPlatformContext.h" + +namespace RNSkia { + +namespace jsi = facebook::jsi; + +class JsiBindGroupLayout + : public JsiSkWrappingSharedPtrHostObject { +public: + JsiBindGroupLayout(std::shared_ptr context, + wgpu::BindGroupLayout m) + : JsiSkWrappingSharedPtrHostObject( + context, std::make_shared(std::move(m))) {} + + // TODO: this fix, use JSI_EXPORT_PROPERTY_GETTERS instead + EXPORT_JSI_API_BRANDNAME(JsiBindGroupLayout, BindGroupLayout) + + /** + * Returns the underlying object from a host object of this type + */ + static wgpu::BindGroupLayout *fromValue(jsi::Runtime &runtime, + const jsi::Value &raw) { + const auto &obj = raw.asObject(runtime); + if (obj.isHostObject(runtime)) { + return obj.asHostObject(runtime)->getObject().get(); + } else { + throw jsi::JSError(runtime, + "Expected a JsiBindGroupLayout object, but got a " + + raw.toString(runtime).utf8(runtime)); + } + } +}; +} // namespace RNSkia diff --git a/package/cpp/wgpu/JsiBindingResource.h b/package/cpp/wgpu/JsiBindingResource.h new file mode 100644 index 0000000000..de668acf28 --- /dev/null +++ b/package/cpp/wgpu/JsiBindingResource.h @@ -0,0 +1,57 @@ +#pragma once +#include +#include +#include + +#include "webgpu.hpp" + +#include + +#include "JsiBuffer.h" +#include "JsiEnums.h" +#include "JsiHostObject.h" +#include "JsiPromises.h" +#include "JsiSkHostObjects.h" +#include "RNSkLog.h" +#include "RNSkPlatformContext.h" + +namespace RNSkia { + +namespace jsi = facebook::jsi; + +class JsiBindingResource + : public JsiSkWrappingSharedPtrHostObject { +public: + JsiBindingResource(std::shared_ptr context, + wgpu::BindingResource m) + : JsiSkWrappingSharedPtrHostObject( + context, std::make_shared(std::move(m))) {} + + // TODO: this fix, use JSI_EXPORT_PROPERTY_GETTERS instead + EXPORT_JSI_API_BRANDNAME(JsiBindingResource, BindingResource) + + /** + * Returns the underlying object from a host object of this type + */ + static wgpu::BindingResource *fromValue(jsi::Runtime &runtime, + const jsi::Value &raw) { + const auto &obj = raw.asObject(runtime); + if (obj.isHostObject(runtime)) { + return obj.asHostObject(runtime)->getObject().get(); + } else { + auto object = new wgpu::BindingResource(); + object->setDefault(); + + if (obj.hasProperty(runtime, "buffer")) { + auto buffer = obj.getProperty(runtime, "buffer"); + + object->buffer = *JsiBuffer::fromValue(runtime, buffer); + } else { + throw jsi::JSError(runtime, + "Missing mandatory prop buffer in BindingResource"); + } + return object; + } + } +}; +} // namespace RNSkia diff --git a/package/cpp/wgpu/JsiBlendComponent.h b/package/cpp/wgpu/JsiBlendComponent.h index 4c6a656573..70670663b8 100644 --- a/package/cpp/wgpu/JsiBlendComponent.h +++ b/package/cpp/wgpu/JsiBlendComponent.h @@ -32,13 +32,14 @@ class JsiBlendComponent /** * Returns the underlying object from a host object of this type */ - static std::shared_ptr - fromValue(jsi::Runtime &runtime, const jsi::Value &raw) { + static wgpu::BlendComponent *fromValue(jsi::Runtime &runtime, + const jsi::Value &raw) { const auto &obj = raw.asObject(runtime); if (obj.isHostObject(runtime)) { - return obj.asHostObject(runtime)->getObject(); + return obj.asHostObject(runtime)->getObject().get(); } else { - auto object = std::make_shared(); + auto object = new wgpu::BlendComponent(); + object->setDefault(); if (obj.hasProperty(runtime, "operation")) { auto operation = obj.getProperty(runtime, "operation"); diff --git a/package/cpp/wgpu/JsiBlendState.h b/package/cpp/wgpu/JsiBlendState.h index 80d4579e8a..ec006e3efe 100644 --- a/package/cpp/wgpu/JsiBlendState.h +++ b/package/cpp/wgpu/JsiBlendState.h @@ -33,18 +33,19 @@ class JsiBlendState /** * Returns the underlying object from a host object of this type */ - static std::shared_ptr fromValue(jsi::Runtime &runtime, - const jsi::Value &raw) { + static wgpu::BlendState *fromValue(jsi::Runtime &runtime, + const jsi::Value &raw) { const auto &obj = raw.asObject(runtime); if (obj.isHostObject(runtime)) { - return obj.asHostObject(runtime)->getObject(); + return obj.asHostObject(runtime)->getObject().get(); } else { - auto object = std::make_shared(); + auto object = new wgpu::BlendState(); + object->setDefault(); if (obj.hasProperty(runtime, "color")) { auto color = obj.getProperty(runtime, "color"); - object->color = *JsiBlendComponent::fromValue(runtime, color).get(); + object->color = *JsiBlendComponent::fromValue(runtime, color); } else { throw jsi::JSError(runtime, "Missing mandatory prop color in BlendState"); @@ -52,7 +53,7 @@ class JsiBlendState if (obj.hasProperty(runtime, "alpha")) { auto alpha = obj.getProperty(runtime, "alpha"); - object->alpha = *JsiBlendComponent::fromValue(runtime, alpha).get(); + object->alpha = *JsiBlendComponent::fromValue(runtime, alpha); } else { throw jsi::JSError(runtime, "Missing mandatory prop alpha in BlendState"); diff --git a/package/cpp/wgpu/JsiBuffer.h b/package/cpp/wgpu/JsiBuffer.h new file mode 100644 index 0000000000..22ed18b39e --- /dev/null +++ b/package/cpp/wgpu/JsiBuffer.h @@ -0,0 +1,67 @@ +#pragma once +#include +#include +#include + +#include "webgpu.hpp" + +#include + +#include "JsiEnums.h" +#include "JsiHostObject.h" +#include "JsiPromises.h" +#include "JsiSkHostObjects.h" +#include "RNSkLog.h" +#include "RNSkPlatformContext.h" + +namespace RNSkia { + +namespace jsi = facebook::jsi; + +class JsiBuffer : public JsiSkWrappingSharedPtrHostObject { +public: + JsiBuffer(std::shared_ptr context, wgpu::Buffer m) + : JsiSkWrappingSharedPtrHostObject( + context, std::make_shared(std::move(m))) {} + + JSI_HOST_FUNCTION(unmap) { + + getObject()->unmap(); + return jsi::Value::undefined(); + } + + JSI_HOST_FUNCTION(getMappedRange) { + + size_t offset = static_cast(arguments[0].getNumber()); + size_t size = static_cast(arguments[1].getNumber()); + auto data = getObject()->getMappedRange(offset, size); + auto arrayBufferCtor = + runtime.global().getPropertyAsFunction(runtime, "ArrayBuffer"); + auto o = + arrayBufferCtor.callAsConstructor(runtime, static_cast(size)) + .getObject(runtime); + auto buf = o.getArrayBuffer(runtime); + memcpy(buf.data(runtime), data, size); + return o; + } + + // TODO: this fix, use JSI_EXPORT_PROPERTY_GETTERS instead + EXPORT_JSI_API_BRANDNAME(JsiBuffer, Buffer) + + JSI_EXPORT_FUNCTIONS(JSI_EXPORT_FUNC(JsiBuffer, unmap), + JSI_EXPORT_FUNC(JsiBuffer, getMappedRange)) + + /** + * Returns the underlying object from a host object of this type + */ + static wgpu::Buffer *fromValue(jsi::Runtime &runtime, const jsi::Value &raw) { + const auto &obj = raw.asObject(runtime); + if (obj.isHostObject(runtime)) { + return obj.asHostObject(runtime)->getObject().get(); + } else { + throw jsi::JSError(runtime, "Expected a JsiBuffer object, but got a " + + raw.toString(runtime).utf8(runtime)); + } + } +}; +} // namespace RNSkia diff --git a/package/cpp/wgpu/JsiBufferBinding.h b/package/cpp/wgpu/JsiBufferBinding.h new file mode 100644 index 0000000000..c27df72c45 --- /dev/null +++ b/package/cpp/wgpu/JsiBufferBinding.h @@ -0,0 +1,57 @@ +#pragma once +#include +#include +#include + +#include "webgpu.hpp" + +#include + +#include "JsiBuffer.h" +#include "JsiEnums.h" +#include "JsiHostObject.h" +#include "JsiPromises.h" +#include "JsiSkHostObjects.h" +#include "RNSkLog.h" +#include "RNSkPlatformContext.h" + +namespace RNSkia { + +namespace jsi = facebook::jsi; + +class JsiBufferBinding + : public JsiSkWrappingSharedPtrHostObject { +public: + JsiBufferBinding(std::shared_ptr context, + wgpu::BufferBinding m) + : JsiSkWrappingSharedPtrHostObject( + context, std::make_shared(std::move(m))) {} + + // TODO: this fix, use JSI_EXPORT_PROPERTY_GETTERS instead + EXPORT_JSI_API_BRANDNAME(JsiBufferBinding, BufferBinding) + + /** + * Returns the underlying object from a host object of this type + */ + static wgpu::BufferBinding *fromValue(jsi::Runtime &runtime, + const jsi::Value &raw) { + const auto &obj = raw.asObject(runtime); + if (obj.isHostObject(runtime)) { + return obj.asHostObject(runtime)->getObject().get(); + } else { + auto object = new wgpu::BufferBinding(); + object->setDefault(); + + if (obj.hasProperty(runtime, "buffer")) { + auto buffer = obj.getProperty(runtime, "buffer"); + + object->buffer = *JsiBuffer::fromValue(runtime, buffer); + } else { + throw jsi::JSError(runtime, + "Missing mandatory prop buffer in BufferBinding"); + } + return object; + } + } +}; +} // namespace RNSkia diff --git a/package/cpp/wgpu/JsiBufferDescriptor.h b/package/cpp/wgpu/JsiBufferDescriptor.h new file mode 100644 index 0000000000..0186a04524 --- /dev/null +++ b/package/cpp/wgpu/JsiBufferDescriptor.h @@ -0,0 +1,74 @@ +#pragma once +#include +#include +#include + +#include "webgpu.hpp" + +#include + +#include "JsiEnums.h" +#include "JsiHostObject.h" +#include "JsiPromises.h" +#include "JsiSkHostObjects.h" +#include "RNSkLog.h" +#include "RNSkPlatformContext.h" + +namespace RNSkia { + +namespace jsi = facebook::jsi; + +class JsiBufferDescriptor + : public JsiSkWrappingSharedPtrHostObject { +public: + JsiBufferDescriptor(std::shared_ptr context, + wgpu::BufferDescriptor m) + : JsiSkWrappingSharedPtrHostObject( + context, std::make_shared(std::move(m))) {} + + // TODO: this fix, use JSI_EXPORT_PROPERTY_GETTERS instead + EXPORT_JSI_API_BRANDNAME(JsiBufferDescriptor, BufferDescriptor) + + /** + * Returns the underlying object from a host object of this type + */ + static wgpu::BufferDescriptor *fromValue(jsi::Runtime &runtime, + const jsi::Value &raw) { + const auto &obj = raw.asObject(runtime); + if (obj.isHostObject(runtime)) { + return obj.asHostObject(runtime)->getObject().get(); + } else { + auto object = new wgpu::BufferDescriptor(); + object->setDefault(); + + if (obj.hasProperty(runtime, "size")) { + auto size = obj.getProperty(runtime, "size"); + + object->size = static_cast(size.getNumber()); + } else { + throw jsi::JSError(runtime, + "Missing mandatory prop size in BufferDescriptor"); + } + if (obj.hasProperty(runtime, "usage")) { + auto usage = obj.getProperty(runtime, "usage"); + + object->usage = static_cast(usage.getNumber()); + } else { + throw jsi::JSError(runtime, + "Missing mandatory prop usage in BufferDescriptor"); + } + if (obj.hasProperty(runtime, "mappedAtCreation")) { + auto mappedAtCreation = obj.getProperty(runtime, "mappedAtCreation"); + + object->mappedAtCreation = + static_cast(mappedAtCreation.getBool()); + } else { + throw jsi::JSError( + runtime, + "Missing mandatory prop mappedAtCreation in BufferDescriptor"); + } + return object; + } + } +}; +} // namespace RNSkia diff --git a/package/cpp/wgpu/JsiColor.h b/package/cpp/wgpu/JsiColor.h index 511aec6220..192d9a6ac4 100644 --- a/package/cpp/wgpu/JsiColor.h +++ b/package/cpp/wgpu/JsiColor.h @@ -30,11 +30,10 @@ class JsiColor : public JsiSkWrappingSharedPtrHostObject { /** * Returns the underlying object from a host object of this type */ - static std::shared_ptr fromValue(jsi::Runtime &runtime, - const jsi::Value &raw) { + static wgpu::Color *fromValue(jsi::Runtime &runtime, const jsi::Value &raw) { const auto &obj = raw.asObject(runtime); if (obj.isHostObject(runtime)) { - return obj.asHostObject(runtime)->getObject(); + return obj.asHostObject(runtime)->getObject().get(); } else { if (obj.isArray(runtime)) { auto jsiArray = obj.asArray(runtime); @@ -43,11 +42,12 @@ class JsiColor : public JsiSkWrappingSharedPtrHostObject { array.push_back(jsiArray.getValueAtIndex(runtime, i).asNumber()); } auto data = array.data(); - auto object = std::make_shared( - wgpu::Color{data[0], data[1], data[2], data[3]}); + auto object = + new wgpu::Color(wgpu::Color{data[0], data[1], data[2], data[3]}); return object; } - auto object = std::make_shared(); + auto object = new wgpu::Color(); + object->setDefault(); if (obj.hasProperty(runtime, "r")) { auto r = obj.getProperty(runtime, "r"); diff --git a/package/cpp/wgpu/JsiColorTargetState.h b/package/cpp/wgpu/JsiColorTargetState.h index 0e1e25f3f9..19b09f31f0 100644 --- a/package/cpp/wgpu/JsiColorTargetState.h +++ b/package/cpp/wgpu/JsiColorTargetState.h @@ -33,14 +33,15 @@ class JsiColorTargetState /** * Returns the underlying object from a host object of this type */ - static std::shared_ptr - fromValue(jsi::Runtime &runtime, const jsi::Value &raw) { + static wgpu::ColorTargetState *fromValue(jsi::Runtime &runtime, + const jsi::Value &raw) { const auto &obj = raw.asObject(runtime); if (obj.isHostObject(runtime)) { - return obj.asHostObject(runtime)->getObject(); + return obj.asHostObject(runtime)->getObject().get(); } else { - auto object = std::make_shared(); - + auto object = new wgpu::ColorTargetState(); + object->setDefault(); + object->writeMask = wgpu::ColorWriteMask::All; if (obj.hasProperty(runtime, "format")) { auto format = obj.getProperty(runtime, "format"); @@ -53,7 +54,7 @@ class JsiColorTargetState if (obj.hasProperty(runtime, "blend")) { auto blend = obj.getProperty(runtime, "blend"); - object->blend = JsiBlendState::fromValue(runtime, blend).get(); + object->blend = JsiBlendState::fromValue(runtime, blend); } if (obj.hasProperty(runtime, "writeMask")) { auto writeMask = obj.getProperty(runtime, "writeMask"); diff --git a/package/cpp/wgpu/JsiCommandBuffer.h b/package/cpp/wgpu/JsiCommandBuffer.h index e2c87b310a..6830b26b87 100644 --- a/package/cpp/wgpu/JsiCommandBuffer.h +++ b/package/cpp/wgpu/JsiCommandBuffer.h @@ -32,11 +32,11 @@ class JsiCommandBuffer /** * Returns the underlying object from a host object of this type */ - static std::shared_ptr fromValue(jsi::Runtime &runtime, - const jsi::Value &raw) { + static wgpu::CommandBuffer *fromValue(jsi::Runtime &runtime, + const jsi::Value &raw) { const auto &obj = raw.asObject(runtime); if (obj.isHostObject(runtime)) { - return obj.asHostObject(runtime)->getObject(); + return obj.asHostObject(runtime)->getObject().get(); } else { throw jsi::JSError(runtime, "Expected a JsiCommandBuffer object, but got a " + diff --git a/package/cpp/wgpu/JsiCommandEncoder.h b/package/cpp/wgpu/JsiCommandEncoder.h index 48d055c672..6fa7322ebe 100644 --- a/package/cpp/wgpu/JsiCommandEncoder.h +++ b/package/cpp/wgpu/JsiCommandEncoder.h @@ -32,7 +32,7 @@ class JsiCommandEncoder JSI_HOST_FUNCTION(beginRenderPass) { auto descriptor = JsiRenderPassDescriptor::fromValue(runtime, arguments[0]); - auto ret = getObject()->beginRenderPass(*descriptor.get()); + auto ret = getObject()->beginRenderPass(*descriptor); return jsi::Object::createFromHostObject( runtime, std::make_shared(getContext(), ret)); } @@ -53,11 +53,11 @@ class JsiCommandEncoder /** * Returns the underlying object from a host object of this type */ - static std::shared_ptr - fromValue(jsi::Runtime &runtime, const jsi::Value &raw) { + static wgpu::CommandEncoder *fromValue(jsi::Runtime &runtime, + const jsi::Value &raw) { const auto &obj = raw.asObject(runtime); if (obj.isHostObject(runtime)) { - return obj.asHostObject(runtime)->getObject(); + return obj.asHostObject(runtime)->getObject().get(); } else { throw jsi::JSError(runtime, "Expected a JsiCommandEncoder object, but got a " + diff --git a/package/cpp/wgpu/JsiCommandEncoderDescriptor.h b/package/cpp/wgpu/JsiCommandEncoderDescriptor.h index dbb15fe092..cf0c4e5d00 100644 --- a/package/cpp/wgpu/JsiCommandEncoderDescriptor.h +++ b/package/cpp/wgpu/JsiCommandEncoderDescriptor.h @@ -34,12 +34,13 @@ class JsiCommandEncoderDescriptor /** * Returns the underlying object from a host object of this type */ - static std::shared_ptr - fromValue(jsi::Runtime &runtime, const jsi::Value &raw) { + static wgpu::CommandEncoderDescriptor *fromValue(jsi::Runtime &runtime, + const jsi::Value &raw) { const auto &obj = raw.asObject(runtime); if (obj.isHostObject(runtime)) { return obj.asHostObject(runtime) - ->getObject(); + ->getObject() + .get(); } else { throw jsi::JSError( runtime, "Expected a JsiCommandEncoderDescriptor object, but got a " + diff --git a/package/cpp/wgpu/JsiContext.h b/package/cpp/wgpu/JsiContext.h index 9999c1eefa..0ead11308a 100644 --- a/package/cpp/wgpu/JsiContext.h +++ b/package/cpp/wgpu/JsiContext.h @@ -31,18 +31,19 @@ class JsiContext : public JsiSkWrappingSharedPtrHostObject { /** * Returns the underlying object from a host object of this type */ - static std::shared_ptr fromValue(jsi::Runtime &runtime, - const jsi::Value &raw) { + static wgpu::Context *fromValue(jsi::Runtime &runtime, + const jsi::Value &raw) { const auto &obj = raw.asObject(runtime); if (obj.isHostObject(runtime)) { - return obj.asHostObject(runtime)->getObject(); + return obj.asHostObject(runtime)->getObject().get(); } else { - auto object = std::make_shared(); + auto object = new wgpu::Context(); + object->setDefault(); if (obj.hasProperty(runtime, "gpu")) { auto gpu = obj.getProperty(runtime, "gpu"); - object->gpu = *JsiGpu::fromValue(runtime, gpu).get(); + object->gpu = *JsiGpu::fromValue(runtime, gpu); } else { throw jsi::JSError(runtime, "Missing mandatory prop gpu in Context"); } diff --git a/package/cpp/wgpu/JsiDepthStencilState.h b/package/cpp/wgpu/JsiDepthStencilState.h index 2a4890b5aa..39a19a91f1 100644 --- a/package/cpp/wgpu/JsiDepthStencilState.h +++ b/package/cpp/wgpu/JsiDepthStencilState.h @@ -33,13 +33,14 @@ class JsiDepthStencilState /** * Returns the underlying object from a host object of this type */ - static std::shared_ptr - fromValue(jsi::Runtime &runtime, const jsi::Value &raw) { + static wgpu::DepthStencilState *fromValue(jsi::Runtime &runtime, + const jsi::Value &raw) { const auto &obj = raw.asObject(runtime); if (obj.isHostObject(runtime)) { - return obj.asHostObject(runtime)->getObject(); + return obj.asHostObject(runtime)->getObject().get(); } else { - auto object = std::make_shared(); + auto object = new wgpu::DepthStencilState(); + object->setDefault(); if (obj.hasProperty(runtime, "format")) { auto format = obj.getProperty(runtime, "format"); @@ -66,13 +67,13 @@ class JsiDepthStencilState auto stencilFront = obj.getProperty(runtime, "stencilFront"); object->stencilFront = - *JsiStencilFaceState::fromValue(runtime, stencilFront).get(); + *JsiStencilFaceState::fromValue(runtime, stencilFront); } if (obj.hasProperty(runtime, "stencilBack")) { auto stencilBack = obj.getProperty(runtime, "stencilBack"); object->stencilBack = - *JsiStencilFaceState::fromValue(runtime, stencilBack).get(); + *JsiStencilFaceState::fromValue(runtime, stencilBack); } if (obj.hasProperty(runtime, "stencilReadMask")) { auto stencilReadMask = obj.getProperty(runtime, "stencilReadMask"); diff --git a/package/cpp/wgpu/JsiDevice.h b/package/cpp/wgpu/JsiDevice.h index 8720462950..5724e92b36 100644 --- a/package/cpp/wgpu/JsiDevice.h +++ b/package/cpp/wgpu/JsiDevice.h @@ -7,6 +7,10 @@ #include +#include "JsiBindGroup.h" +#include "JsiBindGroupDescriptor.h" +#include "JsiBuffer.h" +#include "JsiBufferDescriptor.h" #include "JsiCommandEncoder.h" #include "JsiCommandEncoderDescriptor.h" #include "JsiEnums.h" @@ -18,6 +22,8 @@ #include "JsiShaderModule.h" #include "JsiShaderModuleWGSLDescriptor.h" #include "JsiSkHostObjects.h" +#include "JsiTexture.h" +#include "JsiTextureDescriptor.h" #include "RNSkLog.h" #include "RNSkPlatformContext.h" @@ -38,11 +44,19 @@ class JsiDevice : public JsiSkWrappingSharedPtrHostObject { runtime, std::make_shared(getContext(), ret)); } + JSI_HOST_FUNCTION(createBindGroup) { + auto descriptor = JsiBindGroupDescriptor::fromValue(runtime, arguments[0]); + + auto ret = getObject()->createBindGroup(*descriptor); + return jsi::Object::createFromHostObject( + runtime, std::make_shared(getContext(), ret)); + } + JSI_HOST_FUNCTION(createRenderPipeline) { auto descriptor = JsiRenderPipelineDescriptor::fromValue(runtime, arguments[0]); - auto ret = getObject()->createRenderPipeline(*descriptor.get()); + auto ret = getObject()->createRenderPipeline(*descriptor); return jsi::Object::createFromHostObject( runtime, std::make_shared(getContext(), ret)); } @@ -51,7 +65,7 @@ class JsiDevice : public JsiSkWrappingSharedPtrHostObject { auto moduleDescriptor = JsiShaderModuleWGSLDescriptor::fromValue(runtime, arguments[0]); - auto moduleDescriptorNext = *moduleDescriptor.get(); + auto moduleDescriptorNext = *moduleDescriptor; wgpu::ShaderModuleDescriptor baseModuleDescriptor; baseModuleDescriptor.nextInChain = &moduleDescriptorNext.chain; auto ret = getObject()->createShaderModule(baseModuleDescriptor); @@ -60,33 +74,51 @@ class JsiDevice : public JsiSkWrappingSharedPtrHostObject { } JSI_HOST_FUNCTION(createCommandEncoder) { - auto defaultDescriptor = std::make_shared(); + auto defaultDescriptor = new wgpu::CommandEncoderDescriptor(); auto descriptor = count > 0 ? JsiCommandEncoderDescriptor::fromValue(runtime, arguments[0]) : defaultDescriptor; - auto ret = getObject()->createCommandEncoder(*descriptor.get()); + auto ret = getObject()->createCommandEncoder(*descriptor); return jsi::Object::createFromHostObject( runtime, std::make_shared(getContext(), ret)); } + JSI_HOST_FUNCTION(createBuffer) { + auto descritor = JsiBufferDescriptor::fromValue(runtime, arguments[0]); + + auto ret = getObject()->createBuffer(*descritor); + return jsi::Object::createFromHostObject( + runtime, std::make_shared(getContext(), ret)); + } + + JSI_HOST_FUNCTION(createTexture) { + auto descriptor = JsiTextureDescriptor::fromValue(runtime, arguments[0]); + + auto ret = getObject()->createTexture(*descriptor); + return jsi::Object::createFromHostObject( + runtime, std::make_shared(getContext(), ret)); + } + // TODO: this fix, use JSI_EXPORT_PROPERTY_GETTERS instead JSI_EXPORT_PROPERTY_GETTERS(JSI_EXPORT_PROP_GET(JsiDevice, queue)) - JSI_EXPORT_FUNCTIONS(JSI_EXPORT_FUNC(JsiDevice, createRenderPipeline), + JSI_EXPORT_FUNCTIONS(JSI_EXPORT_FUNC(JsiDevice, createBindGroup), + JSI_EXPORT_FUNC(JsiDevice, createRenderPipeline), JSI_EXPORT_FUNC(JsiDevice, createShaderModule), - JSI_EXPORT_FUNC(JsiDevice, createCommandEncoder)) + JSI_EXPORT_FUNC(JsiDevice, createCommandEncoder), + JSI_EXPORT_FUNC(JsiDevice, createBuffer), + JSI_EXPORT_FUNC(JsiDevice, createTexture)) /** * Returns the underlying object from a host object of this type */ - static std::shared_ptr fromValue(jsi::Runtime &runtime, - const jsi::Value &raw) { + static wgpu::Device *fromValue(jsi::Runtime &runtime, const jsi::Value &raw) { const auto &obj = raw.asObject(runtime); if (obj.isHostObject(runtime)) { - return obj.asHostObject(runtime)->getObject(); + return obj.asHostObject(runtime)->getObject().get(); } else { throw jsi::JSError(runtime, "Expected a JsiDevice object, but got a " + raw.toString(runtime).utf8(runtime)); diff --git a/package/cpp/wgpu/JsiDeviceDescriptor.h b/package/cpp/wgpu/JsiDeviceDescriptor.h index 6cffbfa605..fe48be9409 100644 --- a/package/cpp/wgpu/JsiDeviceDescriptor.h +++ b/package/cpp/wgpu/JsiDeviceDescriptor.h @@ -32,11 +32,11 @@ class JsiDeviceDescriptor /** * Returns the underlying object from a host object of this type */ - static std::shared_ptr - fromValue(jsi::Runtime &runtime, const jsi::Value &raw) { + static wgpu::DeviceDescriptor *fromValue(jsi::Runtime &runtime, + const jsi::Value &raw) { const auto &obj = raw.asObject(runtime); if (obj.isHostObject(runtime)) { - return obj.asHostObject(runtime)->getObject(); + return obj.asHostObject(runtime)->getObject().get(); } else { throw jsi::JSError(runtime, "Expected a JsiDeviceDescriptor object, but got a " + diff --git a/package/cpp/wgpu/JsiExtent3D.h b/package/cpp/wgpu/JsiExtent3D.h new file mode 100644 index 0000000000..1418e516c2 --- /dev/null +++ b/package/cpp/wgpu/JsiExtent3D.h @@ -0,0 +1,61 @@ +#pragma once +#include +#include +#include + +#include "webgpu.hpp" + +#include + +#include "JsiEnums.h" +#include "JsiHostObject.h" +#include "JsiPromises.h" +#include "JsiSkHostObjects.h" +#include "RNSkLog.h" +#include "RNSkPlatformContext.h" + +namespace RNSkia { + +namespace jsi = facebook::jsi; + +class JsiExtent3D : public JsiSkWrappingSharedPtrHostObject { +public: + JsiExtent3D(std::shared_ptr context, wgpu::Extent3D m) + : JsiSkWrappingSharedPtrHostObject( + context, std::make_shared(std::move(m))) {} + + // TODO: this fix, use JSI_EXPORT_PROPERTY_GETTERS instead + EXPORT_JSI_API_BRANDNAME(JsiExtent3D, Extent3D) + + /** + * Returns the underlying object from a host object of this type + */ + static wgpu::Extent3D *fromValue(jsi::Runtime &runtime, + const jsi::Value &raw) { + const auto &obj = raw.asObject(runtime); + if (obj.isHostObject(runtime)) { + return obj.asHostObject(runtime)->getObject().get(); + } else { + auto object = new wgpu::Extent3D(); + object->setDefault(); + + if (obj.hasProperty(runtime, "width")) { + auto width = obj.getProperty(runtime, "width"); + + object->width = static_cast(width.getNumber()); + } else { + throw jsi::JSError(runtime, "Missing mandatory prop width in Extent3D"); + } + if (obj.hasProperty(runtime, "height")) { + auto height = obj.getProperty(runtime, "height"); + + object->height = static_cast(height.getNumber()); + } else { + throw jsi::JSError(runtime, + "Missing mandatory prop height in Extent3D"); + } + return object; + } + } +}; +} // namespace RNSkia diff --git a/package/cpp/wgpu/JsiFragmentState.h b/package/cpp/wgpu/JsiFragmentState.h index fa4c2b5e43..2588206445 100644 --- a/package/cpp/wgpu/JsiFragmentState.h +++ b/package/cpp/wgpu/JsiFragmentState.h @@ -34,18 +34,19 @@ class JsiFragmentState /** * Returns the underlying object from a host object of this type */ - static std::shared_ptr fromValue(jsi::Runtime &runtime, - const jsi::Value &raw) { + static wgpu::FragmentState *fromValue(jsi::Runtime &runtime, + const jsi::Value &raw) { const auto &obj = raw.asObject(runtime); if (obj.isHostObject(runtime)) { - return obj.asHostObject(runtime)->getObject(); + return obj.asHostObject(runtime)->getObject().get(); } else { - auto object = std::make_shared(); + auto object = new wgpu::FragmentState(); + object->setDefault(); if (obj.hasProperty(runtime, "module")) { auto module = obj.getProperty(runtime, "module"); - object->module = *JsiShaderModule::fromValue(runtime, module).get(); + object->module = *JsiShaderModule::fromValue(runtime, module); } else { throw jsi::JSError(runtime, "Missing mandatory prop module in FragmentState"); @@ -63,16 +64,16 @@ class JsiFragmentState auto targets = obj.getProperty(runtime, "targets"); auto jsiArray2 = targets.asObject(runtime).asArray(runtime); auto jsiArray2Size = static_cast(jsiArray2.size(runtime)); - std::vector array2; - array2.reserve(jsiArray2Size); + auto array2 = new std::vector(); + array2->reserve(jsiArray2Size); for (int i = 0; i < jsiArray2Size; i++) { auto element = JsiColorTargetState::fromValue( - runtime, jsiArray2.getValueAtIndex(runtime, i).asObject(runtime)); - array2.push_back(*element.get()); + runtime, jsiArray2.getValueAtIndex(runtime, i)); + array2->push_back(*element); } object->targetCount = jsiArray2Size; - object->targets = array2.data(); + object->targets = array2->data(); } return object; } diff --git a/package/cpp/wgpu/JsiGPU.h b/package/cpp/wgpu/JsiGPU.h index df82e5c96b..30bf9adb2e 100644 --- a/package/cpp/wgpu/JsiGPU.h +++ b/package/cpp/wgpu/JsiGPU.h @@ -27,11 +27,11 @@ class JsiGPU : public JsiSkWrappingSharedPtrHostObject { context, std::make_shared(std::move(m))) {} JSI_HOST_FUNCTION(getPreferredCanvasFormat) { - return jsi::String::createFromUtf8(runtime, "bgra8unorm"); + return jsi::String::createFromUtf8(runtime, "rgba8unorm"); } JSI_HOST_FUNCTION(requestAdapter) { - auto defaultOptions = std::make_shared(); + auto defaultOptions = new wgpu::RequestAdapterOptions(); auto options = count > 0 ? JsiRequestAdapterOptions::fromValue(runtime, arguments[0]) : defaultOptions; @@ -43,7 +43,7 @@ class JsiGPU : public JsiSkWrappingSharedPtrHostObject { options = std::move(options)]( jsi::Runtime &runtime, std::shared_ptr promise) -> void { - auto ret = object->requestAdapter(*options.get()); + auto ret = object->requestAdapter(*options); if (ret == nullptr) { promise->resolve(jsi::Value::null()); } else { @@ -63,11 +63,11 @@ class JsiGPU : public JsiSkWrappingSharedPtrHostObject { /** * Returns the underlying object from a host object of this type */ - static std::shared_ptr fromValue(jsi::Runtime &runtime, - const jsi::Value &raw) { + static wgpu::Instance *fromValue(jsi::Runtime &runtime, + const jsi::Value &raw) { const auto &obj = raw.asObject(runtime); if (obj.isHostObject(runtime)) { - return obj.asHostObject(runtime)->getObject(); + return obj.asHostObject(runtime)->getObject().get(); } else { throw jsi::JSError(runtime, "Expected a JsiGPU object, but got a " + raw.toString(runtime).utf8(runtime)); diff --git a/package/cpp/wgpu/JsiMultisampleState.h b/package/cpp/wgpu/JsiMultisampleState.h index 9453c8f70f..468f554630 100644 --- a/package/cpp/wgpu/JsiMultisampleState.h +++ b/package/cpp/wgpu/JsiMultisampleState.h @@ -32,13 +32,14 @@ class JsiMultisampleState /** * Returns the underlying object from a host object of this type */ - static std::shared_ptr - fromValue(jsi::Runtime &runtime, const jsi::Value &raw) { + static wgpu::MultisampleState *fromValue(jsi::Runtime &runtime, + const jsi::Value &raw) { const auto &obj = raw.asObject(runtime); if (obj.isHostObject(runtime)) { - return obj.asHostObject(runtime)->getObject(); + return obj.asHostObject(runtime)->getObject().get(); } else { - auto object = std::make_shared(); + auto object = new wgpu::MultisampleState(); + object->setDefault(); if (obj.hasProperty(runtime, "count")) { auto count = obj.getProperty(runtime, "count"); diff --git a/package/cpp/wgpu/JsiPrimitiveState.h b/package/cpp/wgpu/JsiPrimitiveState.h index e3fcb719b1..cb797baf6c 100644 --- a/package/cpp/wgpu/JsiPrimitiveState.h +++ b/package/cpp/wgpu/JsiPrimitiveState.h @@ -32,13 +32,14 @@ class JsiPrimitiveState /** * Returns the underlying object from a host object of this type */ - static std::shared_ptr - fromValue(jsi::Runtime &runtime, const jsi::Value &raw) { + static wgpu::PrimitiveState *fromValue(jsi::Runtime &runtime, + const jsi::Value &raw) { const auto &obj = raw.asObject(runtime); if (obj.isHostObject(runtime)) { - return obj.asHostObject(runtime)->getObject(); + return obj.asHostObject(runtime)->getObject().get(); } else { - auto object = std::make_shared(); + auto object = new wgpu::PrimitiveState(); + object->setDefault(); if (obj.hasProperty(runtime, "topology")) { auto topology = obj.getProperty(runtime, "topology"); diff --git a/package/cpp/wgpu/JsiQueue.h b/package/cpp/wgpu/JsiQueue.h index e588dfb9ad..52f678746a 100644 --- a/package/cpp/wgpu/JsiQueue.h +++ b/package/cpp/wgpu/JsiQueue.h @@ -31,27 +31,36 @@ class JsiQueue : public JsiSkWrappingSharedPtrHostObject { auto jsiArraySize = static_cast(jsiArray.size(runtime)); for (int i = 0; i < jsiArraySize; i++) { auto val = jsiArray.getValueAtIndex(runtime, i); - commandBuffers.push_back( - *JsiCommandBuffer::fromValue(runtime, val).get()); + commandBuffers.push_back(*JsiCommandBuffer::fromValue(runtime, val)); } getObject()->submit(commandBuffers); return jsi::Value::undefined(); } + JSI_HOST_FUNCTION(writeBuffer) { + + auto buffer = JsiBuffer::fromValue(runtime, arguments[0]); + auto offset = static_cast(arguments[1].getNumber()); + auto data = arguments[2].getObject(runtime).getArrayBuffer(runtime); + auto size = static_cast(arguments[3].getNumber()); + getObject()->writeBuffer(*buffer, offset, data.data(runtime), size); + return jsi::Value::undefined(); + } + // TODO: this fix, use JSI_EXPORT_PROPERTY_GETTERS instead EXPORT_JSI_API_BRANDNAME(JsiQueue, Queue) - JSI_EXPORT_FUNCTIONS(JSI_EXPORT_FUNC(JsiQueue, submit)) + JSI_EXPORT_FUNCTIONS(JSI_EXPORT_FUNC(JsiQueue, submit), + JSI_EXPORT_FUNC(JsiQueue, writeBuffer)) /** * Returns the underlying object from a host object of this type */ - static std::shared_ptr fromValue(jsi::Runtime &runtime, - const jsi::Value &raw) { + static wgpu::Queue *fromValue(jsi::Runtime &runtime, const jsi::Value &raw) { const auto &obj = raw.asObject(runtime); if (obj.isHostObject(runtime)) { - return obj.asHostObject(runtime)->getObject(); + return obj.asHostObject(runtime)->getObject().get(); } else { throw jsi::JSError(runtime, "Expected a JsiQueue object, but got a " + raw.toString(runtime).utf8(runtime)); diff --git a/package/cpp/wgpu/JsiRenderPassColorAttachment.h b/package/cpp/wgpu/JsiRenderPassColorAttachment.h index 77e83c7240..282c048156 100644 --- a/package/cpp/wgpu/JsiRenderPassColorAttachment.h +++ b/package/cpp/wgpu/JsiRenderPassColorAttachment.h @@ -36,20 +36,22 @@ class JsiRenderPassColorAttachment /** * Returns the underlying object from a host object of this type */ - static std::shared_ptr - fromValue(jsi::Runtime &runtime, const jsi::Value &raw) { + static wgpu::RenderPassColorAttachment *fromValue(jsi::Runtime &runtime, + const jsi::Value &raw) { const auto &obj = raw.asObject(runtime); if (obj.isHostObject(runtime)) { return obj.asHostObject(runtime) - ->getObject(); + ->getObject() + .get(); } else { - auto object = std::make_shared(); + auto object = new wgpu::RenderPassColorAttachment(); + object->setDefault(); object->resolveTarget = nullptr; object->depthSlice = UINT32_MAX; if (obj.hasProperty(runtime, "view")) { auto view = obj.getProperty(runtime, "view"); - object->view = *JsiTextureView::fromValue(runtime, view).get(); + object->view = *JsiTextureView::fromValue(runtime, view); } else { throw jsi::JSError( runtime, @@ -58,7 +60,7 @@ class JsiRenderPassColorAttachment if (obj.hasProperty(runtime, "clearValue")) { auto clearValue = obj.getProperty(runtime, "clearValue"); - object->clearValue = *JsiColor::fromValue(runtime, clearValue).get(); + object->clearValue = *JsiColor::fromValue(runtime, clearValue); } else { throw jsi::JSError( runtime, diff --git a/package/cpp/wgpu/JsiRenderPassDescriptor.h b/package/cpp/wgpu/JsiRenderPassDescriptor.h index 0ee30ea703..5fe24183b2 100644 --- a/package/cpp/wgpu/JsiRenderPassDescriptor.h +++ b/package/cpp/wgpu/JsiRenderPassDescriptor.h @@ -34,28 +34,31 @@ class JsiRenderPassDescriptor /** * Returns the underlying object from a host object of this type */ - static std::shared_ptr - fromValue(jsi::Runtime &runtime, const jsi::Value &raw) { + static wgpu::RenderPassDescriptor *fromValue(jsi::Runtime &runtime, + const jsi::Value &raw) { const auto &obj = raw.asObject(runtime); if (obj.isHostObject(runtime)) { - return obj.asHostObject(runtime)->getObject(); + return obj.asHostObject(runtime) + ->getObject() + .get(); } else { - auto object = std::make_shared(); + auto object = new wgpu::RenderPassDescriptor(); + object->setDefault(); if (obj.hasProperty(runtime, "colorAttachments")) { auto colorAttachments = obj.getProperty(runtime, "colorAttachments"); auto jsiArray0 = colorAttachments.asObject(runtime).asArray(runtime); auto jsiArray0Size = static_cast(jsiArray0.size(runtime)); - std::vector array0; - array0.reserve(jsiArray0Size); + auto array0 = new std::vector(); + array0->reserve(jsiArray0Size); for (int i = 0; i < jsiArray0Size; i++) { auto element = JsiRenderPassColorAttachment::fromValue( - runtime, jsiArray0.getValueAtIndex(runtime, i).asObject(runtime)); - array0.push_back(*element.get()); + runtime, jsiArray0.getValueAtIndex(runtime, i)); + array0->push_back(*element); } object->colorAttachmentCount = jsiArray0Size; - object->colorAttachments = array0.data(); + object->colorAttachments = array0->data(); } else { throw jsi::JSError( runtime, diff --git a/package/cpp/wgpu/JsiRenderPassEncoder.h b/package/cpp/wgpu/JsiRenderPassEncoder.h index 2959f694ec..fd51f40556 100644 --- a/package/cpp/wgpu/JsiRenderPassEncoder.h +++ b/package/cpp/wgpu/JsiRenderPassEncoder.h @@ -30,7 +30,7 @@ class JsiRenderPassEncoder JSI_HOST_FUNCTION(setPipeline) { auto pipeline = JsiRenderPipeline::fromValue(runtime, arguments[0]); - getObject()->setPipeline(*pipeline.get()); + getObject()->setPipeline(*pipeline); return jsi::Value::undefined(); } @@ -69,11 +69,11 @@ class JsiRenderPassEncoder /** * Returns the underlying object from a host object of this type */ - static std::shared_ptr - fromValue(jsi::Runtime &runtime, const jsi::Value &raw) { + static wgpu::RenderPassEncoder *fromValue(jsi::Runtime &runtime, + const jsi::Value &raw) { const auto &obj = raw.asObject(runtime); if (obj.isHostObject(runtime)) { - return obj.asHostObject(runtime)->getObject(); + return obj.asHostObject(runtime)->getObject().get(); } else { throw jsi::JSError(runtime, "Expected a JsiRenderPassEncoder object, but got a " + diff --git a/package/cpp/wgpu/JsiRenderPipeline.h b/package/cpp/wgpu/JsiRenderPipeline.h index c643734ca5..a5c2df751a 100644 --- a/package/cpp/wgpu/JsiRenderPipeline.h +++ b/package/cpp/wgpu/JsiRenderPipeline.h @@ -7,6 +7,7 @@ #include +#include "JsiBindGroupLayout.h" #include "JsiEnums.h" #include "JsiHostObject.h" #include "JsiPromises.h" @@ -26,17 +27,27 @@ class JsiRenderPipeline : JsiSkWrappingSharedPtrHostObject( context, std::make_shared(std::move(m))) {} + JSI_HOST_FUNCTION(getBindGroupLayout) { + auto index = static_cast(arguments[0].getNumber()); + + auto ret = getObject()->getBindGroupLayout(index); + return jsi::Object::createFromHostObject( + runtime, std::make_shared(getContext(), ret)); + } + // TODO: this fix, use JSI_EXPORT_PROPERTY_GETTERS instead EXPORT_JSI_API_BRANDNAME(JsiRenderPipeline, RenderPipeline) + JSI_EXPORT_FUNCTIONS(JSI_EXPORT_FUNC(JsiRenderPipeline, getBindGroupLayout)) + /** * Returns the underlying object from a host object of this type */ - static std::shared_ptr - fromValue(jsi::Runtime &runtime, const jsi::Value &raw) { + static wgpu::RenderPipeline *fromValue(jsi::Runtime &runtime, + const jsi::Value &raw) { const auto &obj = raw.asObject(runtime); if (obj.isHostObject(runtime)) { - return obj.asHostObject(runtime)->getObject(); + return obj.asHostObject(runtime)->getObject().get(); } else { throw jsi::JSError(runtime, "Expected a JsiRenderPipeline object, but got a " + diff --git a/package/cpp/wgpu/JsiRenderPipelineDescriptor.h b/package/cpp/wgpu/JsiRenderPipelineDescriptor.h index 2ce3cc70b1..d595d10549 100644 --- a/package/cpp/wgpu/JsiRenderPipelineDescriptor.h +++ b/package/cpp/wgpu/JsiRenderPipelineDescriptor.h @@ -39,14 +39,16 @@ class JsiRenderPipelineDescriptor /** * Returns the underlying object from a host object of this type */ - static std::shared_ptr - fromValue(jsi::Runtime &runtime, const jsi::Value &raw) { + static wgpu::RenderPipelineDescriptor *fromValue(jsi::Runtime &runtime, + const jsi::Value &raw) { const auto &obj = raw.asObject(runtime); if (obj.isHostObject(runtime)) { return obj.asHostObject(runtime) - ->getObject(); + ->getObject() + .get(); } else { - auto object = std::make_shared(); + auto object = new wgpu::RenderPipelineDescriptor(); + object->setDefault(); object->multisample.count = 1; object->multisample.mask = ~0u; object->multisample.alphaToCoverageEnabled = false; @@ -54,7 +56,7 @@ class JsiRenderPipelineDescriptor if (obj.hasProperty(runtime, "vertex")) { auto vertex = obj.getProperty(runtime, "vertex"); - object->vertex = *JsiVertexState::fromValue(runtime, vertex).get(); + object->vertex = *JsiVertexState::fromValue(runtime, vertex); } else { throw jsi::JSError( runtime, @@ -63,8 +65,7 @@ class JsiRenderPipelineDescriptor if (obj.hasProperty(runtime, "primitive")) { auto primitive = obj.getProperty(runtime, "primitive"); - object->primitive = - *JsiPrimitiveState::fromValue(runtime, primitive).get(); + object->primitive = *JsiPrimitiveState::fromValue(runtime, primitive); } else { throw jsi::JSError( runtime, @@ -74,18 +75,18 @@ class JsiRenderPipelineDescriptor auto depthStencil = obj.getProperty(runtime, "depthStencil"); object->depthStencil = - JsiDepthStencilState::fromValue(runtime, depthStencil).get(); + JsiDepthStencilState::fromValue(runtime, depthStencil); } if (obj.hasProperty(runtime, "multisample")) { auto multisample = obj.getProperty(runtime, "multisample"); object->multisample = - *JsiMultisampleState::fromValue(runtime, multisample).get(); + *JsiMultisampleState::fromValue(runtime, multisample); } if (obj.hasProperty(runtime, "fragment")) { auto fragment = obj.getProperty(runtime, "fragment"); - object->fragment = JsiFragmentState::fromValue(runtime, fragment).get(); + object->fragment = JsiFragmentState::fromValue(runtime, fragment); } return object; } diff --git a/package/cpp/wgpu/JsiRequestAdapterOptions.h b/package/cpp/wgpu/JsiRequestAdapterOptions.h index 649cbf266c..49a2e1443a 100644 --- a/package/cpp/wgpu/JsiRequestAdapterOptions.h +++ b/package/cpp/wgpu/JsiRequestAdapterOptions.h @@ -33,13 +33,16 @@ class JsiRequestAdapterOptions /** * Returns the underlying object from a host object of this type */ - static std::shared_ptr - fromValue(jsi::Runtime &runtime, const jsi::Value &raw) { + static wgpu::RequestAdapterOptions *fromValue(jsi::Runtime &runtime, + const jsi::Value &raw) { const auto &obj = raw.asObject(runtime); if (obj.isHostObject(runtime)) { - return obj.asHostObject(runtime)->getObject(); + return obj.asHostObject(runtime) + ->getObject() + .get(); } else { - auto object = std::make_shared(); + auto object = new wgpu::RequestAdapterOptions(); + object->setDefault(); if (obj.hasProperty(runtime, "powerPreference")) { auto powerPreference = obj.getProperty(runtime, "powerPreference"); diff --git a/package/cpp/wgpu/JsiShaderModule.h b/package/cpp/wgpu/JsiShaderModule.h index c8e45b4d94..8ff9549113 100644 --- a/package/cpp/wgpu/JsiShaderModule.h +++ b/package/cpp/wgpu/JsiShaderModule.h @@ -32,11 +32,11 @@ class JsiShaderModule /** * Returns the underlying object from a host object of this type */ - static std::shared_ptr fromValue(jsi::Runtime &runtime, - const jsi::Value &raw) { + static wgpu::ShaderModule *fromValue(jsi::Runtime &runtime, + const jsi::Value &raw) { const auto &obj = raw.asObject(runtime); if (obj.isHostObject(runtime)) { - return obj.asHostObject(runtime)->getObject(); + return obj.asHostObject(runtime)->getObject().get(); } else { throw jsi::JSError(runtime, "Expected a JsiShaderModule object, but got a " + diff --git a/package/cpp/wgpu/JsiShaderModuleWGSLDescriptor.h b/package/cpp/wgpu/JsiShaderModuleWGSLDescriptor.h index 7b647f039e..f771a60ed1 100644 --- a/package/cpp/wgpu/JsiShaderModuleWGSLDescriptor.h +++ b/package/cpp/wgpu/JsiShaderModuleWGSLDescriptor.h @@ -34,14 +34,16 @@ class JsiShaderModuleWGSLDescriptor : public JsiSkWrappingSharedPtrHostObject< /** * Returns the underlying object from a host object of this type */ - static std::shared_ptr - fromValue(jsi::Runtime &runtime, const jsi::Value &raw) { + static wgpu::ShaderModuleWGSLDescriptor *fromValue(jsi::Runtime &runtime, + const jsi::Value &raw) { const auto &obj = raw.asObject(runtime); if (obj.isHostObject(runtime)) { return obj.asHostObject(runtime) - ->getObject(); + ->getObject() + .get(); } else { - auto object = std::make_shared(); + auto object = new wgpu::ShaderModuleWGSLDescriptor(); + object->setDefault(); object->chain.next = nullptr; object->chain.sType = wgpu::SType::ShaderModuleWGSLDescriptor; if (obj.hasProperty(runtime, "code")) { diff --git a/package/cpp/wgpu/JsiSize.h b/package/cpp/wgpu/JsiSize.h new file mode 100644 index 0000000000..2612072dbd --- /dev/null +++ b/package/cpp/wgpu/JsiSize.h @@ -0,0 +1,69 @@ +#pragma once +#include +#include +#include + +#include "webgpu.hpp" + +#include + +#include "JsiEnums.h" +#include "JsiHostObject.h" +#include "JsiPromises.h" +#include "JsiSkHostObjects.h" +#include "RNSkLog.h" +#include "RNSkPlatformContext.h" + +namespace RNSkia { + +namespace jsi = facebook::jsi; + +class JsiSize : public JsiSkWrappingSharedPtrHostObject { +public: + JsiSize(std::shared_ptr context, wgpu::Size m) + : JsiSkWrappingSharedPtrHostObject( + context, std::make_shared(std::move(m))) {} + + // TODO: this fix, use JSI_EXPORT_PROPERTY_GETTERS instead + EXPORT_JSI_API_BRANDNAME(JsiSize, Size) + + /** + * Returns the underlying object from a host object of this type + */ + static wgpu::Size *fromValue(jsi::Runtime &runtime, const jsi::Value &raw) { + const auto &obj = raw.asObject(runtime); + if (obj.isHostObject(runtime)) { + return obj.asHostObject(runtime)->getObject().get(); + } else { + if (obj.isArray(runtime)) { + auto jsiArray = obj.asArray(runtime); + std::vector array; + for (int i = 0; i < jsiArray.size(runtime); i++) { + array.push_back(jsiArray.getValueAtIndex(runtime, i).asNumber()); + } + auto data = array.data(); + auto object = new wgpu::Size(wgpu::Size{data[0], data[1]}); + return object; + } + auto object = new wgpu::Size(); + object->setDefault(); + + if (obj.hasProperty(runtime, "width")) { + auto width = obj.getProperty(runtime, "width"); + + object->width = static_cast(width.getNumber()); + } else { + throw jsi::JSError(runtime, "Missing mandatory prop width in Size"); + } + if (obj.hasProperty(runtime, "heigth")) { + auto heigth = obj.getProperty(runtime, "heigth"); + + object->heigth = static_cast(heigth.getNumber()); + } else { + throw jsi::JSError(runtime, "Missing mandatory prop heigth in Size"); + } + return object; + } + } +}; +} // namespace RNSkia diff --git a/package/cpp/wgpu/JsiStencilFaceState.h b/package/cpp/wgpu/JsiStencilFaceState.h index b55980c3ea..33d5812431 100644 --- a/package/cpp/wgpu/JsiStencilFaceState.h +++ b/package/cpp/wgpu/JsiStencilFaceState.h @@ -32,13 +32,14 @@ class JsiStencilFaceState /** * Returns the underlying object from a host object of this type */ - static std::shared_ptr - fromValue(jsi::Runtime &runtime, const jsi::Value &raw) { + static wgpu::StencilFaceState *fromValue(jsi::Runtime &runtime, + const jsi::Value &raw) { const auto &obj = raw.asObject(runtime); if (obj.isHostObject(runtime)) { - return obj.asHostObject(runtime)->getObject(); + return obj.asHostObject(runtime)->getObject().get(); } else { - auto object = std::make_shared(); + auto object = new wgpu::StencilFaceState(); + object->setDefault(); if (obj.hasProperty(runtime, "compare")) { auto compare = obj.getProperty(runtime, "compare"); diff --git a/package/cpp/wgpu/JsiTexture.h b/package/cpp/wgpu/JsiTexture.h index 14086242e9..8e9974f7ed 100644 --- a/package/cpp/wgpu/JsiTexture.h +++ b/package/cpp/wgpu/JsiTexture.h @@ -40,11 +40,11 @@ class JsiTexture : public JsiSkWrappingSharedPtrHostObject { /** * Returns the underlying object from a host object of this type */ - static std::shared_ptr fromValue(jsi::Runtime &runtime, - const jsi::Value &raw) { + static wgpu::Texture *fromValue(jsi::Runtime &runtime, + const jsi::Value &raw) { const auto &obj = raw.asObject(runtime); if (obj.isHostObject(runtime)) { - return obj.asHostObject(runtime)->getObject(); + return obj.asHostObject(runtime)->getObject().get(); } else { throw jsi::JSError(runtime, "Expected a JsiTexture object, but got a " + raw.toString(runtime).utf8(runtime)); diff --git a/package/cpp/wgpu/JsiTextureDescriptor.h b/package/cpp/wgpu/JsiTextureDescriptor.h new file mode 100644 index 0000000000..c7333d3af5 --- /dev/null +++ b/package/cpp/wgpu/JsiTextureDescriptor.h @@ -0,0 +1,74 @@ +#pragma once +#include +#include +#include + +#include "webgpu.hpp" + +#include + +#include "JsiEnums.h" +#include "JsiExtent3D.h" +#include "JsiHostObject.h" +#include "JsiPromises.h" +#include "JsiSkHostObjects.h" +#include "RNSkLog.h" +#include "RNSkPlatformContext.h" + +namespace RNSkia { + +namespace jsi = facebook::jsi; + +class JsiTextureDescriptor + : public JsiSkWrappingSharedPtrHostObject { +public: + JsiTextureDescriptor(std::shared_ptr context, + wgpu::TextureDescriptor m) + : JsiSkWrappingSharedPtrHostObject( + context, std::make_shared(std::move(m))) {} + + // TODO: this fix, use JSI_EXPORT_PROPERTY_GETTERS instead + EXPORT_JSI_API_BRANDNAME(JsiTextureDescriptor, TextureDescriptor) + + /** + * Returns the underlying object from a host object of this type + */ + static wgpu::TextureDescriptor *fromValue(jsi::Runtime &runtime, + const jsi::Value &raw) { + const auto &obj = raw.asObject(runtime); + if (obj.isHostObject(runtime)) { + return obj.asHostObject(runtime)->getObject().get(); + } else { + auto object = new wgpu::TextureDescriptor(); + object->setDefault(); + + if (obj.hasProperty(runtime, "size")) { + auto size = obj.getProperty(runtime, "size"); + + object->size = *JsiExtent3D::fromValue(runtime, size); + } else { + throw jsi::JSError(runtime, + "Missing mandatory prop size in TextureDescriptor"); + } + if (obj.hasProperty(runtime, "format")) { + auto format = obj.getProperty(runtime, "format"); + + object->format = + getTextureFormat(format.getString(runtime).utf8(runtime).c_str()); + } else { + throw jsi::JSError( + runtime, "Missing mandatory prop format in TextureDescriptor"); + } + if (obj.hasProperty(runtime, "usage")) { + auto usage = obj.getProperty(runtime, "usage"); + + object->usage = static_cast(usage.getNumber()); + } else { + throw jsi::JSError(runtime, + "Missing mandatory prop usage in TextureDescriptor"); + } + return object; + } + } +}; +} // namespace RNSkia diff --git a/package/cpp/wgpu/JsiTextureView.h b/package/cpp/wgpu/JsiTextureView.h index 665a5673c1..1b50e5699f 100644 --- a/package/cpp/wgpu/JsiTextureView.h +++ b/package/cpp/wgpu/JsiTextureView.h @@ -32,11 +32,11 @@ class JsiTextureView /** * Returns the underlying object from a host object of this type */ - static std::shared_ptr fromValue(jsi::Runtime &runtime, - const jsi::Value &raw) { + static wgpu::TextureView *fromValue(jsi::Runtime &runtime, + const jsi::Value &raw) { const auto &obj = raw.asObject(runtime); if (obj.isHostObject(runtime)) { - return obj.asHostObject(runtime)->getObject(); + return obj.asHostObject(runtime)->getObject().get(); } else { throw jsi::JSError(runtime, "Expected a JsiTextureView object, but got a " + diff --git a/package/cpp/wgpu/JsiVertexState.h b/package/cpp/wgpu/JsiVertexState.h index 18a07a99fa..c1ba822605 100644 --- a/package/cpp/wgpu/JsiVertexState.h +++ b/package/cpp/wgpu/JsiVertexState.h @@ -33,18 +33,19 @@ class JsiVertexState /** * Returns the underlying object from a host object of this type */ - static std::shared_ptr fromValue(jsi::Runtime &runtime, - const jsi::Value &raw) { + static wgpu::VertexState *fromValue(jsi::Runtime &runtime, + const jsi::Value &raw) { const auto &obj = raw.asObject(runtime); if (obj.isHostObject(runtime)) { - return obj.asHostObject(runtime)->getObject(); + return obj.asHostObject(runtime)->getObject().get(); } else { - auto object = std::make_shared(); + auto object = new wgpu::VertexState(); + object->setDefault(); if (obj.hasProperty(runtime, "module")) { auto module = obj.getProperty(runtime, "module"); - object->module = *JsiShaderModule::fromValue(runtime, module).get(); + object->module = *JsiShaderModule::fromValue(runtime, module); } else { throw jsi::JSError(runtime, "Missing mandatory prop module in VertexState"); diff --git a/package/cpp/wgpu/JsiWGPUContext.h b/package/cpp/wgpu/JsiWGPUContext.h index df2133cae4..335ef94cc8 100644 --- a/package/cpp/wgpu/JsiWGPUContext.h +++ b/package/cpp/wgpu/JsiWGPUContext.h @@ -66,7 +66,8 @@ class JsiWGPUContext : public JsiSkWrappingSharedPtrHostObject { JSI_HOST_FUNCTION(runDemo) { auto device = JsiDevice::fromValue(runtime, arguments[0].asObject(runtime)); // auto pipeline2 = - // JsiRenderPipeline::fromValue(runtime, arguments[1].asObject(runtime)); + // JsiRenderPipeline::fromValue(runtime, + // arguments[1].asObject(runtime)); auto commandEncoder = JsiCommandEncoder::fromValue(runtime, arguments[2].asObject(runtime)); auto vertexState = @@ -78,7 +79,7 @@ class JsiWGPUContext : public JsiSkWrappingSharedPtrHostObject { // Vertex fetch // (We don't use any input buffer so far) - pipelineDesc.vertex = *vertexState.get(); + pipelineDesc.vertex = *vertexState; // Primitive assembly and rasterization // Each sequence of 3 vertices is considered as a triangle @@ -96,31 +97,13 @@ class JsiWGPUContext : public JsiSkWrappingSharedPtrHostObject { pipelineDesc.primitive.cullMode = wgpu::CullMode::None; // Fragment shader - pipelineDesc.fragment = fragState.get(); - - // Configure blend state - wgpu::BlendState blendState; - // Usual alpha blending for the color: - blendState.color.srcFactor = wgpu::BlendFactor::SrcAlpha; - blendState.color.dstFactor = wgpu::BlendFactor::OneMinusSrcAlpha; - blendState.color.operation = wgpu::BlendOperation::Add; - // We leave the target alpha untouched: - blendState.alpha.srcFactor = wgpu::BlendFactor::Zero; - blendState.alpha.dstFactor = wgpu::BlendFactor::One; - blendState.alpha.operation = wgpu::BlendOperation::Add; + pipelineDesc.fragment = fragState; - auto adapter = device->getAdapter(); - wgpu::TextureFormat swapChainFormat = _surface->getPreferredFormat(adapter); - wgpu::ColorTargetState colorTarget; - colorTarget.format = swapChainFormat; - colorTarget.blend = &blendState; - colorTarget.writeMask = wgpu::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. - - fragState->targetCount = 1; - fragState->targets = &colorTarget; + // wgpu::ColorTargetState colorTarget; + // colorTarget.format = fragState->targets[0].format; + // colorTarget.writeMask = fragState->targets[0].writeMask; + // fragState->targetCount = 1; + // fragState->targets = &colorTarget; // Depth and stencil tests are not used here pipelineDesc.depthStencil = nullptr; @@ -139,69 +122,6 @@ class JsiWGPUContext : public JsiSkWrappingSharedPtrHostObject { wgpu::RenderPipeline pipeline = device->createRenderPipeline(pipelineDesc); std::cout << "Render pipeline: " << pipeline << std::endl; - // while (true) { - // wgpuInstanceProcessEvents(instance); - - // wgpu::TextureView nextTexture = _swapChain->getCurrentTextureView(); - // if (!nextTexture) { - // RNSkia::RNSkLogger::logToConsole( - // "Cannot acquire next swap chain texture"); - // //return; - // } - - // wgpu::CommandEncoderDescriptor commandEncoderDesc; - // commandEncoderDesc.label = "Command Encoder"; - // wgpu::CommandEncoder encoder = - // device->createCommandEncoder(commandEncoderDesc); - - // wgpu::RenderPassDescriptor renderPassDesc; - - // wgpu::RenderPassColorAttachment renderPassColorAttachment; - // renderPassColorAttachment.view = nextTexture; - // renderPassColorAttachment.resolveTarget = nullptr; - // renderPassColorAttachment.loadOp = wgpu::LoadOp::Clear; - // renderPassColorAttachment.storeOp = wgpu::StoreOp::Store; - // renderPassColorAttachment.depthSlice = UINT32_MAX; - // renderPassColorAttachment.clearValue = wgpu::Color{0.0, 1.0, 1.0, 1.0}; - // renderPassDesc.colorAttachmentCount = 1; - // renderPassDesc.colorAttachments = &renderPassColorAttachment; - - // renderPassDesc.depthStencilAttachment = nullptr; - // renderPassDesc.timestampWriteCount = 0; - // renderPassDesc.timestampWrites = nullptr; - // wgpu::RenderPassEncoder renderPass = - // commandEncoder->beginRenderPass(renderPassDesc); - - // In its overall outline, drawing a triangle is as simple as this: - // Select which render pipeline to use - // renderPass.setPipeline(pipeline); - // // Draw 1 instance of a 3-vertices shape - // renderPass.draw(3, 1, 0, 0); - - // renderPass.end(); - // renderPass.release(); - - // nextTexture.release(); - - // wgpu::CommandBufferDescriptor cmdBufferDescriptor; - // cmdBufferDescriptor.label = "Command buffer"; - // wgpu::CommandBuffer command = encoder.finish(cmdBufferDescriptor); - // encoder.release(); - // std::vector commands; - // commands.push_back(command); - // wgpu::Queue queue = device->getQueue(); - // queue.submit(command); - // command.release(); - - //_swapChain->present(); - // } - - // pipeline.release(); - // shaderModule.release(); - // _swapChain->release(); - // device.release(); - // adapter.release(); - // instance.release(); return jsi::Object::createFromHostObject( runtime, std::make_shared(getContext(), pipeline)); } diff --git a/package/cpp/wgpu/JsiWGPUExtent3D.h b/package/cpp/wgpu/JsiWGPUExtent3D.h new file mode 100644 index 0000000000..f38dc15999 --- /dev/null +++ b/package/cpp/wgpu/JsiWGPUExtent3D.h @@ -0,0 +1,75 @@ +#pragma once +#include +#include +#include + +#include "webgpu.hpp" + +#include + +#include "JsiEnums.h" +#include "JsiHostObject.h" +#include "JsiPromises.h" +#include "JsiSkHostObjects.h" +#include "RNSkLog.h" +#include "RNSkPlatformContext.h" + +namespace RNSkia { + +namespace jsi = facebook::jsi; + +class JsiWGPUExtent3D + : public JsiSkWrappingSharedPtrHostObject { +public: + JsiWGPUExtent3D(std::shared_ptr context, + wgpu::WGPUExtent3D m) + : JsiSkWrappingSharedPtrHostObject( + context, std::make_shared(std::move(m))) {} + + // TODO: this fix, use JSI_EXPORT_PROPERTY_GETTERS instead + EXPORT_JSI_API_BRANDNAME(JsiWGPUExtent3D, WGPUExtent3D) + + /** + * Returns the underlying object from a host object of this type + */ + static wgpu::WGPUExtent3D *fromValue(jsi::Runtime &runtime, + const jsi::Value &raw) { + const auto &obj = raw.asObject(runtime); + if (obj.isHostObject(runtime)) { + return obj.asHostObject(runtime)->getObject().get(); + } else { + if (obj.isArray(runtime)) { + auto jsiArray = obj.asArray(runtime); + std::vector array; + for (int i = 0; i < jsiArray.size(runtime); i++) { + array.push_back(jsiArray.getValueAtIndex(runtime, i).asNumber()); + } + auto data = array.data(); + auto object = + new wgpu::WGPUExtent3D(wgpu::WGPUExtent3D{data[0], data[1]}); + return object; + } + auto object = new wgpu::WGPUExtent3D(); + object->setDefault(); + + if (obj.hasProperty(runtime, "width")) { + auto width = obj.getProperty(runtime, "width"); + + object->width = static_cast(width.getNumber()); + } else { + throw jsi::JSError(runtime, + "Missing mandatory prop width in WGPUExtent3D"); + } + if (obj.hasProperty(runtime, "heigth")) { + auto heigth = obj.getProperty(runtime, "heigth"); + + object->heigth = static_cast(heigth.getNumber()); + } else { + throw jsi::JSError(runtime, + "Missing mandatory prop heigth in WGPUExtent3D"); + } + return object; + } + } +}; +} // namespace RNSkia diff --git a/scripts/generator/common.ts b/scripts/generator/common.ts index 261fbff5b0..66bbfd3d0e 100644 --- a/scripts/generator/common.ts +++ b/scripts/generator/common.ts @@ -4,7 +4,7 @@ import { isEnum } from "./enums"; export const objectName = (name: string) => _.upperFirst(_.camelCase(name)).replace(/Wgsl/g, 'WGSL'); -export const isNumberType = (type: string) => type === "uint32_t" || type === "float" || type === "int32_t" || type === "size_t"; +export const isNumberType = (type: string) => type === "uint64_t" || type === "uint32_t" || type === "float" || type === "int32_t" || type === "size_t"; export const isDouble = (type: string) => type === "double"; export const isAtomicType = (type: string) => type === "bool" || isDouble(type) || isNumberType(type) || type === "string"; @@ -23,7 +23,7 @@ export const unWrapType = (obj: string, type: string, pointer: boolean) => { } else { const name = objectName(type); const className = `Jsi${name}`; - return `${pointer ? '' : '*'}${className}::fromValue(runtime, ${obj}).get()`; + return `${pointer ? '' : '*'}${className}::fromValue(runtime, ${obj})`; } }; diff --git a/scripts/generator/generateObject.ts b/scripts/generator/generateObject.ts index 643181a334..0a80291ee2 100644 --- a/scripts/generator/generateObject.ts +++ b/scripts/generator/generateObject.ts @@ -3,6 +3,13 @@ import { Arg, JSIObject, Method, Property } from "./model"; import { computeDependencies, isAtomicType, isNumberType, objectName, unWrapType } from './common'; import { isEnum } from "./enums"; +const makeSingular = (name: string) => { + if (name === "entries") { + return "entry"; + } + return name.substring(0, name.length - 1); +}; + const generateArg = (index: number, arg: Arg) => { const isArray = arg.type.endsWith("[]"); const name = _.camelCase(arg.name); @@ -31,7 +38,7 @@ for (int i = 0; i < jsiArraySize; i++) { if (arg.optional) { let result = '' if (arg.defaultValue) { - result += `auto default${_.upperFirst(name)} = std::make_shared(); + result += `auto default${_.upperFirst(name)} = new wgpu::${arg.type}(); `; } else if (arg.defaultAtomicValue) { result += `${arg.type} default${_.upperFirst(name)} = ${arg.defaultAtomicValue}; @@ -49,14 +56,14 @@ const unwrapArrayMember = (propName: string, arg: Property, index: number) => { const jsiName = `jsi${_.upperFirst(name)}`; return `auto ${jsiName} = ${propName}.asObject(runtime).asArray(runtime); auto ${jsiName}Size = static_cast(${jsiName}.size(runtime)); -std::vector ${name}; -${name}.reserve(${jsiName}Size); +auto ${name} = new std::vector(); +${name}->reserve(${jsiName}Size); for (int i = 0; i < ${jsiName}Size; i++) { auto element = Jsi${type}::fromValue( runtime, - ${jsiName}.getValueAtIndex(runtime, i).asObject(runtime) + ${jsiName}.getValueAtIndex(runtime, i) ); - ${name}.push_back(*element.get()); + ${name}->push_back(*element); } `; @@ -74,11 +81,11 @@ export const wrapReturnValue = (returns: string | undefined) => { } }; -const argList = (args: Arg[]) => args.map(arg => arg.baseType ? `base${_.upperFirst(arg.name)}`: (isAtomicType(arg.type) || arg.type.endsWith("[]")) ? `${arg.name}` : `*${arg.name}.get()`).join(", "); +const argList = (args: Arg[]) => args.map(arg => arg.baseType ? `base${_.upperFirst(arg.name)}`: (isAtomicType(arg.type) || arg.type.endsWith("[]")) ? `${arg.name}` : `*${arg.name}`).join(", "); const baseType = (arg: Arg) => { return ` -auto ${arg.name}Next = *moduleDescriptor.get(); +auto ${arg.name}Next = *moduleDescriptor; wgpu::${arg.baseType} base${_.upperFirst(arg.name)}; base${_.upperFirst(arg.name)}.nextInChain = &${arg.name}Next.chain;` }; @@ -132,7 +139,8 @@ const generatorAsyncMethod = (method: Method) => { }; const unpackProperties = (name: string, properties: Property[], defaultProperties: string) => { - return `auto object = std::make_shared(); + return `auto object = new wgpu::${name}(); +object->setDefault(); ${defaultProperties} ${properties.map((property, index) => { const propName = _.camelCase(property.name); @@ -140,8 +148,8 @@ ${properties.map((property, index) => { return `if(obj.hasProperty(runtime, "${property.name}")) { auto ${propName} = obj.getProperty(runtime, "${property.name}"); ${isArray ? unwrapArrayMember(propName, property, index) : ''} - ${isArray ? `object->${propName.substring(0, propName.length - 1)}Count = jsiArray${index}Size;` : ``} - object->${propName} = ${isArray ? `array${index}.data()` : unWrapType(propName, property.type, !!property.pointer)}; + ${isArray ? `object->${makeSingular(propName)}Count = jsiArray${index}Size;` : ``} + object->${propName} = ${isArray ? `array${index}->data()` : unWrapType(propName, property.type, !!property.pointer)}; }${property.optional ? `` : ` else { throw jsi::JSError(runtime, "Missing mandatory prop ${property.name} in ${name}"); }`}`; }).join(` `)} @@ -156,7 +164,7 @@ for (int i = 0; i < jsiArray.size(runtime); i++) { array.push_back(jsiArray.getValueAtIndex(runtime, i).asNumber()); } auto data = array.data(); -auto object = std::make_shared(wgpu::${name}{${new Array(size).fill(0).map((_, i) => `data[${i}]`)}}); +auto object = new wgpu::${name}(wgpu::${name}{${new Array(size).fill(0).map((_, i) => `data[${i}]`)}}); return object; }`; }; @@ -209,11 +217,11 @@ ${className}(std::shared_ptr context, ${objectName} m) /** * Returns the underlying object from a host object of this type */ - static std::shared_ptr<${objectName}> fromValue(jsi::Runtime &runtime, + static ${objectName}* fromValue(jsi::Runtime &runtime, const jsi::Value &raw) { const auto &obj = raw.asObject(runtime); if (obj.isHostObject(runtime)) { - return obj.asHostObject<${className}>(runtime)->getObject(); + return obj.asHostObject<${className}>(runtime)->getObject().get(); } else { ${object.properties ? `${object.iterable ? unpackArray(object.name, parseInt(object.iterable, 10)) : ''}${unpackProperties(object.name, object.properties, object.defaultProperties ?? "")}` : `throw jsi::JSError( runtime, diff --git a/scripts/generator/model.ts b/scripts/generator/model.ts index bb5548bfef..75450b211a 100644 --- a/scripts/generator/model.ts +++ b/scripts/generator/model.ts @@ -51,7 +51,7 @@ export const model: JSIObject[] = [ name: "getPreferredCanvasFormat", args: [], returns: "string", - implementation: `return jsi::String::createFromUtf8(runtime, "bgra8unorm");` + implementation: `return jsi::String::createFromUtf8(runtime, "rgba8unorm");` } ] }, @@ -83,6 +83,14 @@ export const model: JSIObject[] = [ returns: "Queue", member: "queue" }, + { + name: "createBindGroup", + args: [{ + name: "descriptor", + type: "BindGroupDescriptor" + }], + returns: "BindGroup" + }, { name: "createRenderPipeline", args: [{ @@ -109,6 +117,83 @@ export const model: JSIObject[] = [ defaultValue: true }], returns: "CommandEncoder", + }, + { + name: "createBuffer", + args: [{ + name: "descritor", + type: "BufferDescriptor" + }], + returns: "Buffer" + }, + { + name: "createTexture", + args: [ + { + name: "descriptor", + type: "TextureDescriptor" + } + ], + returns: "Texture" + } + ] + }, + { + name: "BindGroupDescriptor", + properties: [ + { name: "layout", type: "BindGroupLayout" }, + { name: "entries", type: "BindGroupEntry[]"} + ] + }, + { + name: "BindGroupLayout", + }, + { + name: "BindGroupEntry", + properties: [ + { name: "binding", type: "uint32_t" }, + { name: "buffer", type: "Buffer" } + ] + }, + { + name: "BindGroup" + }, + { + name: "TextureDescriptor", + properties: [ + { name: "size", type: "Extent3D" }, + { name: "format", type: "TextureFormat" }, + { name: "usage", type: "uint32_t" } // TextureUsage + ] + }, + { + "name": "BufferDescriptor", + properties: [ + { name: "size", type: "uint64_t" }, + {"name": "usage", "type": "uint32_t"}, //BufferUsage + {"name": "mappedAtCreation", "type": "bool", "default": "false"} + ] + }, + { + name: "Buffer", + methods: [ + { name: "unmap", args: [] }, + { + name: "getMappedRange", + args: [ + { name: "offset", "type": "size_t", "defaultAtomicValue": "0" }, + {"name": "size", "type": "size_t", "defaultAtomicValue": "SIZE_MAX"} + ], + implementation: ` + size_t offset = static_cast(arguments[0].getNumber()); + size_t size = static_cast(arguments[1].getNumber()); + auto data = getObject()->getMappedRange(offset, size); + auto arrayBufferCtor = + runtime.global().getPropertyAsFunction(runtime, "ArrayBuffer"); + auto o = arrayBufferCtor.callAsConstructor(runtime, static_cast(size)).getObject(runtime); + auto buf = o.getArrayBuffer(runtime); + memcpy(buf.data(runtime), data, size); + return o;` } ] }, @@ -132,6 +217,23 @@ export const model: JSIObject[] = [ type: "CommandBuffer[]", ctype: true }] + }, + { + name: "writeBuffer", + args: [ + // {"name": "buffer", "type": "Buffer"}, + // {"name": "offset", "type": "double"}, + // {"name": "data", "type": "double[]"}, + // {"name": "size", "type": "double"} + ], + implementation: ` + auto buffer = JsiBuffer::fromValue(runtime, arguments[0]); + auto offset = static_cast(arguments[1].getNumber()); + auto data = arguments[2].getObject(runtime).getArrayBuffer(runtime); + auto size = static_cast(arguments[3].getNumber()); + getObject()->writeBuffer(*buffer, offset, data.data(runtime), size); + return jsi::Value::undefined(); + `, } ] }, @@ -186,6 +288,15 @@ object->depthSlice = UINT32_MAX;`, {"name": "storeOp", "type": "StoreOp"} ] }, + { + name: "Extent3D", + // iterable: '2', + properties: [ + {"name": "width", "type": "uint32_t"}, + {"name": "height", "type": "uint32_t"}, + // {"name": "depth", "type": "uint32_t"}, + ] + }, { name: "Color", iterable: '4', @@ -227,6 +338,7 @@ object->chain.sType = wgpu::SType::ShaderModuleWGSLDescriptor;`, }, { name: "ColorTargetState", + defaultProperties: `object->writeMask = wgpu::ColorWriteMask::All;`, properties: [ {"name": "format", "type": "TextureFormat"}, {"name": "blend", "type": "BlendState", "optional": true, pointer: true}, @@ -290,7 +402,17 @@ object->chain.sType = wgpu::SType::ShaderModuleWGSLDescriptor;`, ] }, { - name: "RenderPipeline" + name: "RenderPipeline", + methods: [{ + name: "getBindGroupLayout", + returns: "BindGroupLayout", + args: [ + { + name: "index", + type: "uint32_t" + } + ] + }] }, { name: "DeviceDescriptor",