@nativescript/canvas 2.0.0-beta.8 → 2.0.0-webgpu.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (284) hide show
  1. package/Canvas/common.d.ts +23 -15
  2. package/Canvas/common.js +125 -56
  3. package/Canvas/common.js.map +1 -1
  4. package/Canvas/index.android.d.ts +5 -7
  5. package/Canvas/index.android.js +61 -133
  6. package/Canvas/index.android.js.map +1 -1
  7. package/Canvas/index.d.ts +4 -1
  8. package/Canvas/index.ios.d.ts +6 -6
  9. package/Canvas/index.ios.js +75 -85
  10. package/Canvas/index.ios.js.map +1 -1
  11. package/Canvas2D/CanvasRenderingContext2D/index.d.ts +1 -1
  12. package/Canvas2D/CanvasRenderingContext2D/index.js +8 -11
  13. package/Canvas2D/CanvasRenderingContext2D/index.js.map +1 -1
  14. package/Canvas2D/DOMMatrix/index.d.ts +14 -0
  15. package/Canvas2D/DOMMatrix/index.js +62 -0
  16. package/Canvas2D/DOMMatrix/index.js.map +1 -1
  17. package/Canvas2D/ImageData/index.js +4 -6
  18. package/Canvas2D/ImageData/index.js.map +1 -1
  19. package/ImageAsset/index.d.ts +1 -0
  20. package/ImageAsset/index.js +49 -0
  21. package/ImageAsset/index.js.map +1 -1
  22. package/WebGL/WebGLRenderingContext/index.d.ts +1 -0
  23. package/WebGL/WebGLRenderingContext/index.js +104 -14
  24. package/WebGL/WebGLRenderingContext/index.js.map +1 -1
  25. package/WebGL2/WebGL2RenderingContext/index.d.ts +1 -0
  26. package/WebGL2/WebGL2RenderingContext/index.js +2 -3
  27. package/WebGL2/WebGL2RenderingContext/index.js.map +1 -1
  28. package/WebGPU/Constants.d.ts +36 -0
  29. package/WebGPU/Constants.js +42 -0
  30. package/WebGPU/Constants.js.map +1 -0
  31. package/WebGPU/Errors.d.ts +18 -0
  32. package/WebGPU/Errors.js +21 -0
  33. package/WebGPU/Errors.js.map +1 -0
  34. package/WebGPU/GPU.d.ts +13 -0
  35. package/WebGPU/GPU.js +35 -0
  36. package/WebGPU/GPU.js.map +1 -0
  37. package/WebGPU/GPUAdapter.d.ts +23 -0
  38. package/WebGPU/GPUAdapter.js +62 -0
  39. package/WebGPU/GPUAdapter.js.map +1 -0
  40. package/WebGPU/GPUAdapterInfo.d.ts +9 -0
  41. package/WebGPU/GPUAdapterInfo.js +24 -0
  42. package/WebGPU/GPUAdapterInfo.js.map +1 -0
  43. package/WebGPU/GPUBindGroup.d.ts +5 -0
  44. package/WebGPU/GPUBindGroup.js +12 -0
  45. package/WebGPU/GPUBindGroup.js.map +1 -0
  46. package/WebGPU/GPUBindGroupLayout.d.ts +5 -0
  47. package/WebGPU/GPUBindGroupLayout.js +12 -0
  48. package/WebGPU/GPUBindGroupLayout.js.map +1 -0
  49. package/WebGPU/GPUBuffer.d.ts +15 -0
  50. package/WebGPU/GPUBuffer.js +54 -0
  51. package/WebGPU/GPUBuffer.js.map +1 -0
  52. package/WebGPU/GPUCanvasContext.d.ts +33 -0
  53. package/WebGPU/GPUCanvasContext.js +67 -0
  54. package/WebGPU/GPUCanvasContext.js.map +1 -0
  55. package/WebGPU/GPUCommandBuffer.d.ts +5 -0
  56. package/WebGPU/GPUCommandBuffer.js +12 -0
  57. package/WebGPU/GPUCommandBuffer.js.map +1 -0
  58. package/WebGPU/GPUCommandEncoder.d.ts +41 -0
  59. package/WebGPU/GPUCommandEncoder.js +105 -0
  60. package/WebGPU/GPUCommandEncoder.js.map +1 -0
  61. package/WebGPU/GPUComputePassEncoder.d.ts +16 -0
  62. package/WebGPU/GPUComputePassEncoder.js +50 -0
  63. package/WebGPU/GPUComputePassEncoder.js.map +1 -0
  64. package/WebGPU/GPUComputePipeline.d.ts +7 -0
  65. package/WebGPU/GPUComputePipeline.js +16 -0
  66. package/WebGPU/GPUComputePipeline.js.map +1 -0
  67. package/WebGPU/GPUDevice.d.ts +173 -0
  68. package/WebGPU/GPUDevice.js +381 -0
  69. package/WebGPU/GPUDevice.js.map +1 -0
  70. package/WebGPU/GPUDeviceLostInfo.d.ts +1 -0
  71. package/WebGPU/GPUDeviceLostInfo.js +10 -0
  72. package/WebGPU/GPUDeviceLostInfo.js.map +1 -0
  73. package/WebGPU/GPUExternalTexture.d.ts +5 -0
  74. package/WebGPU/GPUExternalTexture.js +12 -0
  75. package/WebGPU/GPUExternalTexture.js.map +1 -0
  76. package/WebGPU/GPUPipelineLayout.d.ts +5 -0
  77. package/WebGPU/GPUPipelineLayout.js +12 -0
  78. package/WebGPU/GPUPipelineLayout.js.map +1 -0
  79. package/WebGPU/GPUQuerySet.d.ts +5 -0
  80. package/WebGPU/GPUQuerySet.js +12 -0
  81. package/WebGPU/GPUQuerySet.js.map +1 -0
  82. package/WebGPU/GPUQueue.d.ts +14 -0
  83. package/WebGPU/GPUQueue.js +77 -0
  84. package/WebGPU/GPUQueue.js.map +1 -0
  85. package/WebGPU/GPURenderBundle.d.ts +5 -0
  86. package/WebGPU/GPURenderBundle.js +12 -0
  87. package/WebGPU/GPURenderBundle.js.map +1 -0
  88. package/WebGPU/GPURenderBundleEncoder.d.ts +20 -0
  89. package/WebGPU/GPURenderBundleEncoder.js +61 -0
  90. package/WebGPU/GPURenderBundleEncoder.js.map +1 -0
  91. package/WebGPU/GPURenderPassEncoder.d.ts +29 -0
  92. package/WebGPU/GPURenderPassEncoder.js +94 -0
  93. package/WebGPU/GPURenderPassEncoder.js.map +1 -0
  94. package/WebGPU/GPURenderPipeline.d.ts +7 -0
  95. package/WebGPU/GPURenderPipeline.js +16 -0
  96. package/WebGPU/GPURenderPipeline.js.map +1 -0
  97. package/WebGPU/GPUSampler.d.ts +5 -0
  98. package/WebGPU/GPUSampler.js +12 -0
  99. package/WebGPU/GPUSampler.js.map +1 -0
  100. package/WebGPU/GPUShaderModule.d.ts +6 -0
  101. package/WebGPU/GPUShaderModule.js +15 -0
  102. package/WebGPU/GPUShaderModule.js.map +1 -0
  103. package/WebGPU/GPUTexture.d.ts +16 -0
  104. package/WebGPU/GPUTexture.js +41 -0
  105. package/WebGPU/GPUTexture.js.map +1 -0
  106. package/WebGPU/GPUTextureView.d.ts +5 -0
  107. package/WebGPU/GPUTextureView.js +12 -0
  108. package/WebGPU/GPUTextureView.js.map +1 -0
  109. package/WebGPU/Interfaces.d.ts +155 -0
  110. package/WebGPU/Interfaces.js +2 -0
  111. package/WebGPU/Interfaces.js.map +1 -0
  112. package/WebGPU/Types.d.ts +39 -0
  113. package/WebGPU/Types.js +2 -0
  114. package/WebGPU/Types.js.map +1 -0
  115. package/WebGPU/Utils.d.ts +1 -0
  116. package/WebGPU/Utils.js +75 -0
  117. package/WebGPU/Utils.js.map +1 -0
  118. package/WebGPU/index.d.ts +28 -0
  119. package/WebGPU/index.js +29 -0
  120. package/WebGPU/index.js.map +1 -0
  121. package/index.d.ts +1 -1
  122. package/index.js +22 -1
  123. package/index.js.map +1 -1
  124. package/package.json +1 -4
  125. package/platforms/android/canvas-release.aar +0 -0
  126. package/platforms/ios/CanvasNative.xcframework/ios-arm64/CanvasNative.framework/CanvasNative +0 -0
  127. package/platforms/ios/CanvasNative.xcframework/ios-arm64/CanvasNative.framework/Headers/CanvasNative-Swift.h +23 -23
  128. package/platforms/ios/CanvasNative.xcframework/ios-arm64/CanvasNative.framework/Headers/canvas_ios.h +47 -8
  129. package/platforms/ios/CanvasNative.xcframework/ios-arm64/CanvasNative.framework/Headers/canvas_native.h +2280 -103
  130. package/platforms/ios/CanvasNative.xcframework/ios-arm64/CanvasNative.framework/Info.plist +0 -0
  131. package/platforms/ios/CanvasNative.xcframework/ios-arm64/CanvasNative.framework/Modules/CanvasNative.swiftmodule/Project/arm64-apple-ios.swiftsourceinfo +0 -0
  132. package/platforms/ios/CanvasNative.xcframework/ios-arm64/CanvasNative.framework/Modules/CanvasNative.swiftmodule/arm64-apple-ios.abi.json +1564 -3814
  133. package/platforms/ios/CanvasNative.xcframework/ios-arm64/CanvasNative.framework/Modules/CanvasNative.swiftmodule/arm64-apple-ios.private.swiftinterface +27 -34
  134. package/platforms/ios/CanvasNative.xcframework/ios-arm64/CanvasNative.framework/Modules/CanvasNative.swiftmodule/arm64-apple-ios.swiftdoc +0 -0
  135. package/platforms/ios/CanvasNative.xcframework/ios-arm64/CanvasNative.framework/Modules/CanvasNative.swiftmodule/arm64-apple-ios.swiftinterface +27 -34
  136. package/platforms/ios/CanvasNative.xcframework/ios-arm64/dSYMs/CanvasNative.framework.dSYM/Contents/Resources/DWARF/CanvasNative +0 -0
  137. package/platforms/ios/CanvasNative.xcframework/ios-arm64/dSYMs/CanvasNative.framework.dSYM/Contents/Resources/Relocations/aarch64/CanvasNative.yml +602 -664
  138. package/platforms/ios/CanvasNative.xcframework/ios-arm64_x86_64-simulator/CanvasNative.framework/CanvasNative +0 -0
  139. package/platforms/ios/CanvasNative.xcframework/ios-arm64_x86_64-simulator/CanvasNative.framework/Headers/CanvasNative-Swift.h +46 -46
  140. package/platforms/ios/CanvasNative.xcframework/ios-arm64_x86_64-simulator/CanvasNative.framework/Headers/canvas_ios.h +47 -8
  141. package/platforms/ios/CanvasNative.xcframework/ios-arm64_x86_64-simulator/CanvasNative.framework/Headers/canvas_native.h +2280 -103
  142. package/platforms/ios/CanvasNative.xcframework/ios-arm64_x86_64-simulator/CanvasNative.framework/Info.plist +0 -0
  143. package/platforms/ios/CanvasNative.xcframework/ios-arm64_x86_64-simulator/CanvasNative.framework/Modules/CanvasNative.swiftmodule/Project/arm64-apple-ios-simulator.swiftsourceinfo +0 -0
  144. package/platforms/ios/CanvasNative.xcframework/ios-arm64_x86_64-simulator/CanvasNative.framework/Modules/CanvasNative.swiftmodule/Project/x86_64-apple-ios-simulator.swiftsourceinfo +0 -0
  145. package/platforms/ios/CanvasNative.xcframework/ios-arm64_x86_64-simulator/CanvasNative.framework/Modules/CanvasNative.swiftmodule/arm64-apple-ios-simulator.abi.json +1564 -3814
  146. package/platforms/ios/CanvasNative.xcframework/ios-arm64_x86_64-simulator/CanvasNative.framework/Modules/CanvasNative.swiftmodule/arm64-apple-ios-simulator.private.swiftinterface +27 -34
  147. package/platforms/ios/CanvasNative.xcframework/ios-arm64_x86_64-simulator/CanvasNative.framework/Modules/CanvasNative.swiftmodule/arm64-apple-ios-simulator.swiftdoc +0 -0
  148. package/platforms/ios/CanvasNative.xcframework/ios-arm64_x86_64-simulator/CanvasNative.framework/Modules/CanvasNative.swiftmodule/arm64-apple-ios-simulator.swiftinterface +27 -34
  149. package/platforms/ios/CanvasNative.xcframework/ios-arm64_x86_64-simulator/CanvasNative.framework/Modules/CanvasNative.swiftmodule/x86_64-apple-ios-simulator.abi.json +1564 -3814
  150. package/platforms/ios/CanvasNative.xcframework/ios-arm64_x86_64-simulator/CanvasNative.framework/Modules/CanvasNative.swiftmodule/x86_64-apple-ios-simulator.private.swiftinterface +27 -34
  151. package/platforms/ios/CanvasNative.xcframework/ios-arm64_x86_64-simulator/CanvasNative.framework/Modules/CanvasNative.swiftmodule/x86_64-apple-ios-simulator.swiftdoc +0 -0
  152. package/platforms/ios/CanvasNative.xcframework/ios-arm64_x86_64-simulator/CanvasNative.framework/Modules/CanvasNative.swiftmodule/x86_64-apple-ios-simulator.swiftinterface +27 -34
  153. package/platforms/ios/CanvasNative.xcframework/ios-arm64_x86_64-simulator/CanvasNative.framework/_CodeSignature/CodeResources +31 -31
  154. package/platforms/ios/CanvasNative.xcframework/ios-arm64_x86_64-simulator/dSYMs/CanvasNative.framework.dSYM/Contents/Resources/DWARF/CanvasNative +0 -0
  155. package/platforms/ios/CanvasNative.xcframework/ios-arm64_x86_64-simulator/dSYMs/CanvasNative.framework.dSYM/Contents/Resources/Relocations/aarch64/CanvasNative.yml +604 -663
  156. package/platforms/ios/CanvasNative.xcframework/ios-arm64_x86_64-simulator/dSYMs/CanvasNative.framework.dSYM/Contents/Resources/Relocations/x86_64/CanvasNative.yml +638 -642
  157. package/platforms/ios/build.xcconfig +3 -1
  158. package/platforms/ios/src/cpp/Caches.h +69 -1
  159. package/platforms/ios/src/cpp/CanvasJSIModule.cpp +320 -395
  160. package/platforms/ios/src/cpp/CanvasJSIModule.h +7 -1
  161. package/platforms/ios/src/cpp/Helpers.h +43 -8
  162. package/platforms/ios/src/cpp/ImageAssetImpl.cpp +35 -37
  163. package/platforms/ios/src/cpp/ImageAssetImpl.h +14 -10
  164. package/platforms/ios/src/cpp/ImageBitmapImpl.cpp +2 -2
  165. package/platforms/ios/src/cpp/ImageBitmapImpl.h +1 -1
  166. package/platforms/ios/src/cpp/canvas2d/CanvasPattern.cpp +0 -10
  167. package/platforms/ios/src/cpp/canvas2d/CanvasRenderingContext2DImpl.cpp +41 -4
  168. package/platforms/ios/src/cpp/canvas2d/MatrixImpl.cpp +409 -3
  169. package/platforms/ios/src/cpp/canvas2d/MatrixImpl.h +27 -0
  170. package/platforms/ios/src/cpp/webgl/WebGLRenderingContext.cpp +131 -149
  171. package/platforms/ios/src/cpp/webgl2/WebGL2RenderingContext.cpp +1766 -1659
  172. package/platforms/ios/src/cpp/webgpu/GPUAdapterImpl.cpp +302 -0
  173. package/platforms/ios/src/cpp/webgpu/GPUAdapterImpl.h +63 -0
  174. package/platforms/ios/src/cpp/webgpu/GPUAdapterInfoImpl.cpp +174 -0
  175. package/platforms/ios/src/cpp/webgpu/GPUAdapterInfoImpl.h +58 -0
  176. package/platforms/ios/src/cpp/webgpu/GPUBindGroupImpl.cpp +53 -0
  177. package/platforms/ios/src/cpp/webgpu/GPUBindGroupImpl.h +45 -0
  178. package/platforms/ios/src/cpp/webgpu/GPUBindGroupLayoutImpl.cpp +53 -0
  179. package/platforms/ios/src/cpp/webgpu/GPUBindGroupLayoutImpl.h +45 -0
  180. package/platforms/ios/src/cpp/webgpu/GPUBufferImpl.cpp +229 -0
  181. package/platforms/ios/src/cpp/webgpu/GPUBufferImpl.h +59 -0
  182. package/platforms/ios/src/cpp/webgpu/GPUCanvasContextImpl.cpp +317 -0
  183. package/platforms/ios/src/cpp/webgpu/GPUCanvasContextImpl.h +55 -0
  184. package/platforms/ios/src/cpp/webgpu/GPUCommandBufferImpl.cpp +54 -0
  185. package/platforms/ios/src/cpp/webgpu/GPUCommandBufferImpl.h +45 -0
  186. package/platforms/ios/src/cpp/webgpu/GPUCommandEncoderImpl.cpp +1087 -0
  187. package/platforms/ios/src/cpp/webgpu/GPUCommandEncoderImpl.h +69 -0
  188. package/platforms/ios/src/cpp/webgpu/GPUComputePassEncoderImpl.cpp +260 -0
  189. package/platforms/ios/src/cpp/webgpu/GPUComputePassEncoderImpl.h +62 -0
  190. package/platforms/ios/src/cpp/webgpu/GPUComputePipelineImpl.cpp +84 -0
  191. package/platforms/ios/src/cpp/webgpu/GPUComputePipelineImpl.h +49 -0
  192. package/platforms/ios/src/cpp/webgpu/GPUDeviceImpl.cpp +2741 -0
  193. package/platforms/ios/src/cpp/webgpu/GPUDeviceImpl.h +95 -0
  194. package/platforms/ios/src/cpp/webgpu/GPUImpl.cpp +186 -0
  195. package/platforms/ios/src/cpp/webgpu/GPUImpl.h +55 -0
  196. package/platforms/ios/src/cpp/webgpu/GPUPipelineLayoutImpl.cpp +54 -0
  197. package/platforms/ios/src/cpp/webgpu/GPUPipelineLayoutImpl.h +46 -0
  198. package/platforms/ios/src/cpp/webgpu/GPUQuerySetImpl.cpp +137 -0
  199. package/platforms/ios/src/cpp/webgpu/GPUQuerySetImpl.h +55 -0
  200. package/platforms/ios/src/cpp/webgpu/GPUQueueImpl.cpp +521 -0
  201. package/platforms/ios/src/cpp/webgpu/GPUQueueImpl.h +56 -0
  202. package/platforms/ios/src/cpp/webgpu/GPURenderBundleEncoderImpl.cpp +469 -0
  203. package/platforms/ios/src/cpp/webgpu/GPURenderBundleEncoderImpl.h +71 -0
  204. package/platforms/ios/src/cpp/webgpu/GPURenderBundleImpl.cpp +53 -0
  205. package/platforms/ios/src/cpp/webgpu/GPURenderBundleImpl.h +45 -0
  206. package/platforms/ios/src/cpp/webgpu/GPURenderPassEncoderImpl.cpp +653 -0
  207. package/platforms/ios/src/cpp/webgpu/GPURenderPassEncoderImpl.h +85 -0
  208. package/platforms/ios/src/cpp/webgpu/GPURenderPipelineImpl.cpp +84 -0
  209. package/platforms/ios/src/cpp/webgpu/GPURenderPipelineImpl.h +49 -0
  210. package/platforms/ios/src/cpp/webgpu/GPUSamplerImpl.cpp +53 -0
  211. package/platforms/ios/src/cpp/webgpu/GPUSamplerImpl.h +45 -0
  212. package/platforms/ios/src/cpp/webgpu/GPUShaderModuleImpl.cpp +56 -0
  213. package/platforms/ios/src/cpp/webgpu/GPUShaderModuleImpl.h +45 -0
  214. package/platforms/ios/src/cpp/webgpu/GPUSupportedLimitsImpl.cpp +1304 -0
  215. package/platforms/ios/src/cpp/webgpu/GPUSupportedLimitsImpl.h +288 -0
  216. package/platforms/ios/src/cpp/webgpu/GPUTextureImpl.cpp +360 -0
  217. package/platforms/ios/src/cpp/webgpu/GPUTextureImpl.h +75 -0
  218. package/platforms/ios/src/cpp/webgpu/GPUTextureViewImpl.cpp +53 -0
  219. package/platforms/ios/src/cpp/webgpu/GPUTextureViewImpl.h +45 -0
  220. package/platforms/ios/src/cpp/webgpu/GPUUtils.h +178 -0
  221. package/SVG/Circle.d.ts +0 -11
  222. package/SVG/Circle.js +0 -21
  223. package/SVG/Circle.js.map +0 -1
  224. package/SVG/ClipPath.d.ts +0 -4
  225. package/SVG/ClipPath.js +0 -9
  226. package/SVG/ClipPath.js.map +0 -1
  227. package/SVG/Defs.d.ts +0 -4
  228. package/SVG/Defs.js +0 -9
  229. package/SVG/Defs.js.map +0 -1
  230. package/SVG/Ellipse.d.ts +0 -13
  231. package/SVG/Ellipse.js +0 -26
  232. package/SVG/Ellipse.js.map +0 -1
  233. package/SVG/G.d.ts +0 -7
  234. package/SVG/G.js +0 -9
  235. package/SVG/G.js.map +0 -1
  236. package/SVG/Image.d.ts +0 -11
  237. package/SVG/Image.js +0 -40
  238. package/SVG/Image.js.map +0 -1
  239. package/SVG/Line.d.ts +0 -13
  240. package/SVG/Line.js +0 -26
  241. package/SVG/Line.js.map +0 -1
  242. package/SVG/LinearGradient.d.ts +0 -10
  243. package/SVG/LinearGradient.js +0 -13
  244. package/SVG/LinearGradient.js.map +0 -1
  245. package/SVG/Path.d.ts +0 -7
  246. package/SVG/Path.js +0 -14
  247. package/SVG/Path.js.map +0 -1
  248. package/SVG/Pattern.d.ts +0 -4
  249. package/SVG/Pattern.js +0 -9
  250. package/SVG/Pattern.js.map +0 -1
  251. package/SVG/Polygon.d.ts +0 -7
  252. package/SVG/Polygon.js +0 -14
  253. package/SVG/Polygon.js.map +0 -1
  254. package/SVG/Polyline.d.ts +0 -7
  255. package/SVG/Polyline.js +0 -14
  256. package/SVG/Polyline.js.map +0 -1
  257. package/SVG/Rect.d.ts +0 -8
  258. package/SVG/Rect.js +0 -13
  259. package/SVG/Rect.js.map +0 -1
  260. package/SVG/SVG.d.ts +0 -32
  261. package/SVG/SVG.js +0 -204
  262. package/SVG/SVG.js.map +0 -1
  263. package/SVG/SVGItem.d.ts +0 -5
  264. package/SVG/SVGItem.js +0 -8
  265. package/SVG/SVGItem.js.map +0 -1
  266. package/SVG/Stop.d.ts +0 -5
  267. package/SVG/Stop.js +0 -9
  268. package/SVG/Stop.js.map +0 -1
  269. package/SVG/Symbol.d.ts +0 -4
  270. package/SVG/Symbol.js +0 -9
  271. package/SVG/Symbol.js.map +0 -1
  272. package/SVG/Text.d.ts +0 -14
  273. package/SVG/Text.js +0 -26
  274. package/SVG/Text.js.map +0 -1
  275. package/SVG/Use.d.ts +0 -4
  276. package/SVG/Use.js +0 -9
  277. package/SVG/Use.js.map +0 -1
  278. package/SVG/index.d.ts +0 -18
  279. package/SVG/index.js +0 -19
  280. package/SVG/index.js.map +0 -1
  281. package/platforms/ios/src/cpp/PerIsolateData.cpp +0 -49
  282. package/platforms/ios/src/cpp/PerIsolateData.h +0 -54
  283. package/platforms/ios/src/cpp/URLImpl.cpp +0 -464
  284. package/platforms/ios/src/cpp/URLImpl.h +0 -121
@@ -0,0 +1,2741 @@
1
+ //
2
+ // Created by Osei Fortune on 18/06/2024.
3
+ //
4
+
5
+ #include "GPUDeviceImpl.h"
6
+ #include "Caches.h"
7
+ #include "GPUAdapterImpl.h"
8
+ #include "GPUQueueImpl.h"
9
+ #include "GPUCommandEncoderImpl.h"
10
+ #include "GPUShaderModuleImpl.h"
11
+ #include "GPUPipelineLayoutImpl.h"
12
+ #include "GPURenderPipelineImpl.h"
13
+ #include "JSICallback.h"
14
+ #include "GPUBindGroupImpl.h"
15
+ #include "GPUBindGroupLayoutImpl.h"
16
+ #include "GPUSamplerImpl.h"
17
+ #include "GPUTextureViewImpl.h"
18
+ #include "GPUBufferImpl.h"
19
+ #include "GPUTextureImpl.h"
20
+ #include "GPUComputePipelineImpl.h"
21
+ #include "GPUQuerySetImpl.h"
22
+ #include "GPURenderBundleEncoderImpl.h"
23
+ #include "GPUUtils.h"
24
+
25
+ GPUDeviceImpl::GPUDeviceImpl(const CanvasGPUDevice *device) : device_(device) {}
26
+
27
+ const CanvasGPUDevice *GPUDeviceImpl::GetGPUDevice() {
28
+ return this->device_;
29
+ }
30
+
31
+
32
+ void GPUDeviceImpl::Init(v8::Local<v8::Object> canvasModule, v8::Isolate *isolate) {
33
+ v8::Locker locker(isolate);
34
+ v8::Isolate::Scope isolate_scope(isolate);
35
+ v8::HandleScope handle_scope(isolate);
36
+
37
+ auto ctor = GetCtor(isolate);
38
+ auto context = isolate->GetCurrentContext();
39
+ auto func = ctor->GetFunction(context).ToLocalChecked();
40
+
41
+ canvasModule->Set(context, ConvertToV8String(isolate, "GPUDevice"), func).FromJust();;
42
+ }
43
+
44
+ GPUDeviceImpl *GPUDeviceImpl::GetPointer(const v8::Local<v8::Object> &object) {
45
+ auto ptr = object->GetAlignedPointerFromInternalField(0);
46
+ if (ptr == nullptr) {
47
+ return nullptr;
48
+ }
49
+ return static_cast<GPUDeviceImpl *>(ptr);
50
+ }
51
+
52
+ v8::Local<v8::FunctionTemplate> GPUDeviceImpl::GetCtor(v8::Isolate *isolate) {
53
+ auto cache = Caches::Get(isolate);
54
+ auto ctor = cache->GPUDeviceTmpl.get();
55
+ if (ctor != nullptr) {
56
+ return ctor->Get(isolate);
57
+ }
58
+
59
+ v8::Local<v8::FunctionTemplate> ctorTmpl = v8::FunctionTemplate::New(isolate);
60
+ ctorTmpl->InstanceTemplate()->SetInternalFieldCount(2);
61
+ ctorTmpl->SetClassName(ConvertToV8String(isolate, "GPUDevice"));
62
+
63
+ auto tmpl = ctorTmpl->InstanceTemplate();
64
+ tmpl->SetInternalFieldCount(2);
65
+
66
+ tmpl->SetLazyDataProperty(
67
+ ConvertToV8String(isolate, "features"),
68
+ GetFeatures
69
+ );
70
+
71
+ tmpl->SetLazyDataProperty(
72
+ ConvertToV8String(isolate, "queue"),
73
+ GetQueue
74
+ );
75
+
76
+ tmpl->SetLazyDataProperty(
77
+ ConvertToV8String(isolate, "limits"),
78
+ GetLimits
79
+ );
80
+
81
+ tmpl->SetLazyDataProperty(
82
+ ConvertToV8String(isolate, "lost"),
83
+ GetLost
84
+ );
85
+
86
+ tmpl->Set(
87
+ ConvertToV8String(isolate, "createBindGroup"),
88
+ v8::FunctionTemplate::New(isolate, &CreateBindGroup));
89
+
90
+ tmpl->Set(
91
+ ConvertToV8String(isolate, "createBindGroupLayout"),
92
+ v8::FunctionTemplate::New(isolate, &CreateBindGroupLayout));
93
+
94
+ tmpl->Set(
95
+ ConvertToV8String(isolate, "createBuffer"),
96
+ v8::FunctionTemplate::New(isolate, &CreateBuffer));
97
+
98
+ tmpl->Set(
99
+ ConvertToV8String(isolate, "createCommandEncoder"),
100
+ v8::FunctionTemplate::New(isolate, &CreateCommandEncoder));
101
+
102
+ tmpl->Set(
103
+ ConvertToV8String(isolate, "createComputePipeline"),
104
+ v8::FunctionTemplate::New(isolate, &CreateComputePipeline));
105
+
106
+ tmpl->Set(
107
+ ConvertToV8String(isolate, "createPipelineLayout"),
108
+ v8::FunctionTemplate::New(isolate, &CreatePipelineLayout));
109
+
110
+ tmpl->Set(
111
+ ConvertToV8String(isolate, "createQuerySet"),
112
+ v8::FunctionTemplate::New(isolate, &CreateQuerySet));
113
+
114
+ tmpl->Set(
115
+ ConvertToV8String(isolate, "createRenderBundleEncoder"),
116
+ v8::FunctionTemplate::New(isolate, &CreateRenderBundleEncoder));
117
+
118
+ tmpl->Set(
119
+ ConvertToV8String(isolate, "createRenderPipeline"),
120
+ v8::FunctionTemplate::New(isolate, &CreateRenderPipeline));
121
+
122
+ tmpl->Set(
123
+ ConvertToV8String(isolate, "createSampler"),
124
+ v8::FunctionTemplate::New(isolate, &CreateSampler));
125
+
126
+ tmpl->Set(
127
+ ConvertToV8String(isolate, "createShaderModule"),
128
+ v8::FunctionTemplate::New(isolate, &CreateShaderModule));
129
+
130
+ tmpl->Set(
131
+ ConvertToV8String(isolate, "createTexture"),
132
+ v8::FunctionTemplate::New(isolate, &CreateTexture));
133
+
134
+ tmpl->Set(
135
+ ConvertToV8String(isolate, "destroy"),
136
+ v8::FunctionTemplate::New(isolate, &Destroy));
137
+
138
+ tmpl->Set(
139
+ ConvertToV8String(isolate, "popErrorScope"),
140
+ v8::FunctionTemplate::New(isolate, &PopErrorScope));
141
+
142
+ tmpl->Set(
143
+ ConvertToV8String(isolate, "pushErrorScope"),
144
+ v8::FunctionTemplate::New(isolate, &PushErrorScope));
145
+
146
+
147
+ tmpl->Set(
148
+ ConvertToV8String(isolate, "setuncapturederror"),
149
+ v8::FunctionTemplate::New(isolate, &SetUncapturedError));
150
+
151
+
152
+ cache->GPUDeviceTmpl =
153
+ std::make_unique<v8::Persistent<v8::FunctionTemplate>>(isolate, ctorTmpl);
154
+ return ctorTmpl;
155
+ }
156
+
157
+ void
158
+ GPUDeviceImpl::SetUncapturedError(const v8::FunctionCallbackInfo<v8::Value> &args) {
159
+ auto *ptr = GetPointer(args.This());
160
+ if (ptr == nullptr) {
161
+ return;
162
+ }
163
+ auto isolate = args.GetIsolate();
164
+ auto cb = args[0];
165
+ auto callback = new JSICallback(isolate, cb.As<v8::Function>());
166
+
167
+ canvas_native_webgpu_device_set_uncaptured_error_callback(ptr->GetGPUDevice(),
168
+ [](CanvasGPUErrorType type, char *msg,
169
+ void *data) {
170
+
171
+ auto cb = static_cast<JSICallback *>(data);
172
+
173
+ v8::Isolate *isolate = cb->isolate_;
174
+ v8::Locker locker(isolate);
175
+ v8::Isolate::Scope isolate_scope(
176
+ isolate);
177
+ v8::HandleScope handle_scope(
178
+ isolate);
179
+ v8::Local<v8::Function> callback = cb->callback_->Get(
180
+ isolate);
181
+ v8::Local<v8::Context> context = callback->GetCreationContextChecked();
182
+ v8::Context::Scope context_scope(
183
+ context);
184
+ v8::Local<v8::Value> typ;
185
+ v8::Local<v8::Value> message;
186
+ switch (type) {
187
+ case CanvasGPUErrorType::CanvasGPUErrorTypeNone:
188
+ typ = v8::Number::New(
189
+ isolate, 0);
190
+ message = v8::Null(
191
+ isolate);
192
+ break;
193
+ case CanvasGPUErrorType::CanvasGPUErrorTypeLost:
194
+ typ = v8::Number::New(
195
+ isolate, 1);
196
+ message = v8::Null(
197
+ isolate);
198
+ break;
199
+ case CanvasGPUErrorType::CanvasGPUErrorTypeOutOfMemory:
200
+ typ = v8::Number::New(
201
+ isolate, 2);
202
+ message = v8::Null(
203
+ isolate);
204
+ break;
205
+ case CanvasGPUErrorType::CanvasGPUErrorTypeValidation:
206
+ typ = v8::Number::New(
207
+ isolate, 3);
208
+ message = ConvertToV8String(
209
+ isolate, msg);
210
+ break;
211
+ case CanvasGPUErrorType::CanvasGPUErrorTypeInternal:
212
+ typ = v8::Number::New(
213
+ isolate, 4);
214
+ message = v8::Null(
215
+ isolate);
216
+ break;
217
+ }
218
+ v8::Local<v8::Value> args[2] = {
219
+ typ, message
220
+ };
221
+
222
+ callback->Call(context,
223
+ context->Global(),
224
+ 2, args);
225
+
226
+ // todo clean up
227
+ // delete static_cast<JSICallback *>(data);
228
+
229
+ }, callback);
230
+
231
+
232
+ }
233
+
234
+
235
+ void
236
+ GPUDeviceImpl::GetFeatures(v8::Local<v8::Name> name,
237
+ const v8::PropertyCallbackInfo<v8::Value> &info) {
238
+ auto ptr = GetPointer(info.This());
239
+ auto isolate = info.GetIsolate();
240
+ if (ptr != nullptr) {
241
+ auto context = isolate->GetCurrentContext();
242
+
243
+ auto features = canvas_native_webgpu_device_get_features(ptr->GetGPUDevice());
244
+
245
+ auto len = canvas_native_string_buffer_get_length(features);
246
+
247
+ auto map = v8::Map::New(isolate);
248
+ for (int i = 0; i < len; ++i) {
249
+ auto item = canvas_native_string_buffer_get_value_at(features, i);
250
+ if (item != nullptr) {
251
+ auto keyValue = ConvertToV8OneByteString(isolate, (char *) item);
252
+ map->Set(context, keyValue, keyValue);
253
+ canvas_native_string_destroy(item);
254
+ }
255
+
256
+ }
257
+ canvas_native_string_buffer_destroy(features);
258
+
259
+ info.GetReturnValue().Set(map);
260
+
261
+ return;
262
+ }
263
+
264
+ info.GetReturnValue().Set(v8::Map::New(info.GetIsolate()));
265
+ }
266
+
267
+
268
+ void
269
+ GPUDeviceImpl::GetLimits(v8::Local<v8::Name> name,
270
+ const v8::PropertyCallbackInfo<v8::Value> &info) {
271
+ auto ptr = GetPointer(info.This());
272
+ if (ptr != nullptr) {
273
+ auto limits = canvas_native_webgpu_device_get_limits(ptr->GetGPUDevice());
274
+
275
+ auto ret = GPUSupportedLimitsImpl::NewInstance(info.GetIsolate(),
276
+ new GPUSupportedLimitsImpl(limits));
277
+ info.GetReturnValue().Set(ret);
278
+ return;
279
+ }
280
+ info.GetReturnValue().SetUndefined();
281
+ }
282
+
283
+
284
+ void
285
+ GPUDeviceImpl::GetQueue(v8::Local<v8::Name> name,
286
+ const v8::PropertyCallbackInfo<v8::Value> &info) {
287
+ auto ptr = GetPointer(info.This());
288
+ if (ptr != nullptr) {
289
+ auto queue = canvas_native_webgpu_device_get_queue(ptr->GetGPUDevice());
290
+ auto ret = GPUQueueImpl::NewInstance(info.GetIsolate(),
291
+ new GPUQueueImpl(queue));
292
+ info.GetReturnValue().Set(ret);
293
+ return;
294
+ }
295
+ info.GetReturnValue().SetUndefined();
296
+ }
297
+
298
+
299
+ void
300
+ GPUDeviceImpl::GetLost(v8::Local<v8::Name> name,
301
+ const v8::PropertyCallbackInfo<v8::Value> &info) {
302
+ auto ptr = GetPointer(info.This());
303
+ auto isolate = info.GetIsolate();
304
+ auto resolver = v8::Promise::Resolver::New(isolate->GetCurrentContext()).ToLocalChecked();
305
+ info.GetReturnValue().Set(resolver->GetPromise());
306
+ if (ptr != nullptr) {
307
+ v8::Global<v8::Promise::Resolver> promise(isolate, resolver);
308
+ auto callback = new PromiseCallback{
309
+ isolate,
310
+ std::move(promise)
311
+ };
312
+
313
+ canvas_native_webgpu_device_set_lost_callback(ptr->GetGPUDevice(),
314
+ [](int32_t reason, char *message,
315
+ void *data) {
316
+ if (data != nullptr) {
317
+ auto func = static_cast<PromiseCallback *>(data);
318
+ if (func->isolate != nullptr) {
319
+ v8::Isolate *isolate = func->isolate;
320
+ v8::Locker locker(isolate);
321
+ v8::Isolate::Scope isolate_scope(
322
+ isolate);
323
+ v8::HandleScope handle_scope(
324
+ isolate);
325
+ v8::Local<v8::Promise::Resolver> callback = func->callback.Get(
326
+ isolate);
327
+ v8::Local<v8::Context> context = callback->GetCreationContextChecked();
328
+ v8::Context::Scope context_scope(
329
+ context);
330
+
331
+ auto ret = v8::Object::New(
332
+ isolate);
333
+ if (message == nullptr) {
334
+ ret->Set(context,
335
+ ConvertToV8String(
336
+ isolate,
337
+ "message"),
338
+ v8::String::Empty(
339
+ isolate));
340
+ } else {
341
+ ret->Set(context,
342
+ ConvertToV8String(
343
+ isolate,
344
+ "message"),
345
+ ConvertToV8String(
346
+ isolate,
347
+ message));
348
+ canvas_native_string_destroy(
349
+ message);
350
+ }
351
+
352
+ ret->Set(context,
353
+ ConvertToV8String(
354
+ isolate,
355
+ "reason"),
356
+ v8::Int32::New(isolate,
357
+ reason)).IsJust();
358
+
359
+
360
+ callback->Resolve(context, ret);
361
+ delete static_cast<PromiseCallback *>(data);
362
+ }
363
+ }
364
+
365
+ }, callback);
366
+ }
367
+ }
368
+
369
+
370
+ void GPUDeviceImpl::CreateBindGroup(const v8::FunctionCallbackInfo<v8::Value> &args) {
371
+ GPUDeviceImpl *ptr = GetPointer(args.This());
372
+ if (ptr == nullptr) {
373
+ return;
374
+ }
375
+ auto isolate = args.GetIsolate();
376
+ auto context = isolate->GetCurrentContext();
377
+ char *label = nullptr;
378
+
379
+ auto optionsVal = args[0];
380
+
381
+ if (optionsVal->IsObject()) {
382
+ auto options = optionsVal.As<v8::Object>();
383
+ v8::Local<v8::Value> labelVal;
384
+ options->Get(context, ConvertToV8String(isolate, "label")).ToLocal(&labelVal);
385
+
386
+ if (!labelVal.IsEmpty() && labelVal->IsString()) {
387
+ label = *v8::String::Utf8Value(isolate, labelVal);
388
+ }
389
+
390
+ const CanvasGPUBindGroupLayout *layout = nullptr;
391
+
392
+
393
+ v8::Local<v8::Value> layoutVal;
394
+ options->Get(context, ConvertToV8String(isolate, "layout")).ToLocal(&layoutVal);
395
+
396
+ if (!layoutVal.IsEmpty() && layoutVal->IsObject()) {
397
+ auto layoutObj = layoutVal.As<v8::Object>();
398
+ auto layoutImpl = GPUBindGroupLayoutImpl::GetPointer(layoutObj);
399
+ if (layoutImpl != nullptr) {
400
+ layout = layoutImpl->GetBindGroupLayout();
401
+ }
402
+ }
403
+
404
+ std::vector<CanvasBindGroupEntry> entries;
405
+
406
+ v8::Local<v8::Value> entriesVal;
407
+ options->Get(context, ConvertToV8String(isolate, "entries")).ToLocal(&entriesVal);
408
+
409
+ if (!entriesVal.IsEmpty() && entriesVal->IsArray()) {
410
+ auto entriesArray = entriesVal.As<v8::Array>();
411
+ auto len = entriesArray->Length();
412
+ for (int i = 0; i < len; i++) {
413
+ v8::Local<v8::Value> entryVal;
414
+ entriesArray->Get(context, i).ToLocal(&entryVal);
415
+ if (!entryVal.IsEmpty() && entryVal->IsObject()) {
416
+ auto entryObj = entryVal.As<v8::Object>();
417
+ auto binding = entryObj->Get(context, ConvertToV8String(isolate,
418
+ "binding")).ToLocalChecked()->Uint32Value(
419
+ context).FromJust();
420
+ v8::Local<v8::Value> resourceVal;
421
+ entryObj->Get(context, ConvertToV8String(isolate, "resource")).ToLocal(
422
+ &resourceVal);
423
+
424
+ auto resourceType = GetNativeType(resourceVal);
425
+ switch (resourceType) {
426
+ case NativeType::GPUSampler: {
427
+ auto sampler = GPUSamplerImpl::GetPointer(resourceVal.As<v8::Object>());
428
+ if (sampler != nullptr) {
429
+ auto resource = CanvasBindGroupEntryResource{
430
+ CanvasBindGroupEntryResourceSampler,
431
+ };
432
+ resource.sampler = sampler->GetSampler();
433
+ CanvasBindGroupEntry entry{binding, resource};
434
+ entries.push_back(entry);
435
+ }
436
+
437
+ }
438
+ break;
439
+ case NativeType::GPUTextureView: {
440
+ auto textureView = GPUTextureViewImpl::GetPointer(
441
+ resourceVal.As<v8::Object>());
442
+ if (textureView != nullptr) {
443
+ auto resource = CanvasBindGroupEntryResource{
444
+ CanvasBindGroupEntryResourceTextureView,
445
+ };
446
+ resource.texture_view = textureView->GetTextureView();
447
+ CanvasBindGroupEntry entry{binding, resource};
448
+ entries.push_back(entry);
449
+ }
450
+ }
451
+ break;
452
+ default: {
453
+ if (!resourceVal.IsEmpty() && resourceVal->IsObject()) {
454
+ auto resourceObj = resourceVal.As<v8::Object>();
455
+ v8::Local<v8::Value> bufferVal;
456
+ resourceObj->Get(context,
457
+ ConvertToV8String(isolate, "buffer")).ToLocal(
458
+ &bufferVal);
459
+ if (GetNativeType(bufferVal) == NativeType::GPUBuffer) {
460
+ auto bufferObj = bufferVal.As<v8::Object>();
461
+ auto buffer = GPUBufferImpl::GetPointer(bufferObj);
462
+ if (buffer != nullptr) {
463
+ auto resource = CanvasBindGroupEntryResource{
464
+ CanvasBindGroupEntryResourceBuffer,
465
+ };
466
+ int64_t offset = -1;
467
+
468
+ v8::Local<v8::Value> offsetVal;
469
+ bufferObj->Get(context,
470
+ ConvertToV8String(isolate,
471
+ "offset")).ToLocal(
472
+ &offsetVal);
473
+ if (!offsetVal.IsEmpty() && offsetVal->IsNumber()) {
474
+ offset = (int64_t) offsetVal->NumberValue(
475
+ context).ToChecked();
476
+ }
477
+
478
+ int64_t size = -1;
479
+
480
+ v8::Local<v8::Value> sizeVal;
481
+ bufferObj->Get(context,
482
+ ConvertToV8String(isolate, "size")).ToLocal(
483
+ &offsetVal);
484
+ if (!sizeVal.IsEmpty() && sizeVal->IsNumber()) {
485
+ size = (int64_t) sizeVal->NumberValue(
486
+ context).ToChecked();
487
+ }
488
+
489
+ resource.buffer = CanvasBufferBinding{
490
+ buffer->GetGPUBuffer(), offset, size
491
+ };
492
+
493
+ CanvasBindGroupEntry entry{binding, resource};
494
+ entries.push_back(entry);
495
+ }
496
+ }
497
+ }
498
+
499
+ }
500
+ break;
501
+ }
502
+
503
+ }
504
+ }
505
+ }
506
+
507
+
508
+ auto bind_group = canvas_native_webgpu_device_create_bind_group(ptr->GetGPUDevice(), label,
509
+ layout, entries.data(),
510
+ entries.size());
511
+
512
+ if (bind_group != nullptr) {
513
+ auto ret = GPUBindGroupImpl::NewInstance(isolate, new GPUBindGroupImpl(bind_group));
514
+ args.GetReturnValue().Set(ret);
515
+ return;
516
+ }
517
+ }
518
+
519
+ args.GetReturnValue().SetUndefined();
520
+ }
521
+
522
+ void GPUDeviceImpl::CreateBindGroupLayout(const v8::FunctionCallbackInfo<v8::Value> &args) {
523
+ GPUDeviceImpl *ptr = GetPointer(args.This());
524
+ if (ptr == nullptr) {
525
+ return;
526
+ }
527
+ auto isolate = args.GetIsolate();
528
+ auto context = isolate->GetCurrentContext();
529
+ char *label = nullptr;
530
+
531
+ auto optionsVal = args[0];
532
+
533
+ if (optionsVal->IsObject()) {
534
+ auto options = optionsVal.As<v8::Object>();
535
+ v8::Local<v8::Value> labelVal;
536
+ options->Get(context, ConvertToV8String(isolate, "label")).ToLocal(&labelVal);
537
+
538
+ if (!labelVal.IsEmpty() && labelVal->IsString()) {
539
+ label = *v8::String::Utf8Value(isolate, labelVal);
540
+ }
541
+
542
+
543
+ std::vector<CanvasBindGroupLayoutEntry> entries;
544
+
545
+ v8::Local<v8::Value> entriesVal;
546
+ options->Get(context, ConvertToV8String(isolate, "entries")).ToLocal(&entriesVal);
547
+
548
+ if (!entriesVal.IsEmpty() && entriesVal->IsArray()) {
549
+ auto entriesArray = entriesVal.As<v8::Array>();
550
+ auto len = entriesArray->Length();
551
+ for (int i = 0; i < len; i++) {
552
+ v8::Local<v8::Value> entryVal;
553
+ entriesArray->Get(context, i).ToLocal(&entryVal);
554
+ if (!entryVal.IsEmpty() && entryVal->IsObject()) {
555
+ auto entryObj = entryVal.As<v8::Object>();
556
+ auto binding = entryObj->Get(context, ConvertToV8String(isolate,
557
+ "binding")).ToLocalChecked()->Uint32Value(
558
+ context).FromJust();
559
+ v8::Local<v8::Value> resourceVal;
560
+ entryObj->Get(context, ConvertToV8String(isolate, "resource")).ToLocal(
561
+ &resourceVal);
562
+
563
+
564
+ auto visibility = entryObj->Get(context, ConvertToV8String(isolate,
565
+ "visibility")).ToLocalChecked()->Uint32Value(
566
+ context).FromJust();
567
+
568
+
569
+ v8::Local<v8::Value> bufferVal;
570
+
571
+ entryObj->Get(context, ConvertToV8String(isolate, "buffer")).ToLocal(
572
+ &bufferVal);
573
+
574
+
575
+ if (!bufferVal.IsEmpty() && bufferVal->IsObject()) {
576
+ auto bufferObj = bufferVal.As<v8::Object>();
577
+ v8::Local<v8::Value> bufferType;
578
+ bufferObj->Get(context, ConvertToV8String(isolate, "type")).ToLocal(
579
+ &bufferType);
580
+
581
+ CanvasBufferBindingType type = CanvasBufferBindingTypeUniform;
582
+
583
+ if (!bufferType.IsEmpty() && bufferType->IsString()) {
584
+ auto typeStr = ConvertFromV8String(isolate, bufferType);
585
+ if (typeStr == "read-only-storage") {
586
+ type = CanvasBufferBindingTypeReadOnlyStorage;
587
+ } else if (typeStr == "storage") {
588
+ type = CanvasBufferBindingTypeStorage;
589
+ } else if (typeStr == "uniform") {
590
+ type = CanvasBufferBindingTypeUniform;
591
+ }
592
+ }
593
+
594
+ bool has_dynamic_offset = false;
595
+
596
+ v8::Local<v8::Value> hasDynamicOffsetVal;
597
+ bufferObj->Get(context,
598
+ ConvertToV8String(isolate, "hasDynamicOffset ")).ToLocal(
599
+ &hasDynamicOffsetVal);
600
+
601
+
602
+ if (!hasDynamicOffsetVal.IsEmpty() && hasDynamicOffsetVal->IsBoolean()) {
603
+ has_dynamic_offset = hasDynamicOffsetVal->BooleanValue(isolate);
604
+ }
605
+
606
+ int64_t min_binding_size = -1;
607
+
608
+ v8::Local<v8::Value> minBindingSizeVal;
609
+ bufferObj->Get(context,
610
+ ConvertToV8String(isolate, "minBindingSize ")).ToLocal(
611
+ &minBindingSizeVal);
612
+
613
+
614
+ if (!minBindingSizeVal.IsEmpty() && minBindingSizeVal->IsNumber()) {
615
+ min_binding_size = (int64_t) minBindingSizeVal->NumberValue(
616
+ context).ToChecked();
617
+ }
618
+
619
+ CanvasBindingType buffer{
620
+ CanvasBindingTypeBuffer
621
+ };
622
+
623
+ buffer.buffer = CanvasBufferBindingLayout{
624
+ type, has_dynamic_offset, min_binding_size
625
+ };
626
+
627
+
628
+ CanvasBindGroupLayoutEntry entry{
629
+ binding,
630
+ visibility,
631
+ buffer
632
+ };
633
+
634
+ entries.push_back(entry);
635
+
636
+ continue;
637
+ }
638
+
639
+
640
+ v8::Local<v8::Value> externalTextureVal;
641
+
642
+ entryObj->Get(context, ConvertToV8String(isolate, "externalTexture")).ToLocal(
643
+ &externalTextureVal);
644
+
645
+ if (!externalTextureVal.IsEmpty() && externalTextureVal->IsObject()) {
646
+ // todo
647
+ // CanvasBindingType buffer{
648
+ // CanvasBindingTypeTexture
649
+ // };
650
+ //
651
+ // buffer.buffer = CanvasBufferBindingLayout{
652
+ // type, has_dynamic_offset, min_binding_size
653
+ // };
654
+ //
655
+ //
656
+ // CanvasBindGroupLayoutEntry entry{
657
+ // binding,
658
+ // visibility,
659
+ // buffer
660
+ // };
661
+
662
+ continue;
663
+ }
664
+
665
+
666
+ v8::Local<v8::Value> samplerVal;
667
+
668
+ entryObj->Get(context, ConvertToV8String(isolate, "sampler")).ToLocal(
669
+ &samplerVal);
670
+
671
+ if (!samplerVal.IsEmpty() && samplerVal->IsObject()) {
672
+ auto samplerObj = samplerVal.As<v8::Object>();
673
+ v8::Local<v8::Value> samplerType;
674
+ samplerObj->Get(context, ConvertToV8String(isolate, "type")).ToLocal(
675
+ &samplerType);
676
+
677
+ CanvasSamplerBindingType type = CanvasSamplerBindingTypeFiltering;
678
+
679
+ if (!samplerType.IsEmpty() && samplerType->IsString()) {
680
+ auto typeStr = ConvertFromV8String(isolate, samplerType);
681
+ if (typeStr == "comparison") {
682
+ type = CanvasSamplerBindingTypeComparison;
683
+ } else if (typeStr == "non-filtering") {
684
+ type = CanvasSamplerBindingTypeNonFiltering;
685
+ } else if (typeStr == "filtering") {
686
+ type = CanvasSamplerBindingTypeFiltering;
687
+ }
688
+ }
689
+
690
+
691
+ CanvasBindingType sampler{
692
+ CanvasBindingTypeSampler
693
+ };
694
+
695
+ sampler.sampler = CanvasSamplerBindingLayout{
696
+ type
697
+ };
698
+
699
+
700
+ CanvasBindGroupLayoutEntry entry{
701
+ binding,
702
+ visibility,
703
+ sampler
704
+ };
705
+
706
+ entries.push_back(entry);
707
+
708
+ continue;
709
+
710
+ }
711
+
712
+
713
+ v8::Local<v8::Value> storageTextureVal;
714
+
715
+ entryObj->Get(context, ConvertToV8String(isolate, "storageTexture")).ToLocal(
716
+ &storageTextureVal);
717
+
718
+ if (!storageTextureVal.IsEmpty() && storageTextureVal->IsObject()) {
719
+ auto storageTextureObj = storageTextureVal.As<v8::Object>();
720
+
721
+ CanvasBindingType storage{
722
+ CanvasBindingTypeStorageTexture
723
+ };
724
+
725
+ CanvasStorageTextureAccess access = CanvasStorageTextureAccessWriteOnly;
726
+
727
+ v8::Local<v8::Value> accessVal;
728
+
729
+ storageTextureObj->Get(context,
730
+ ConvertToV8String(isolate, "access")).ToLocal(
731
+ &accessVal);
732
+
733
+
734
+ if (!accessVal.IsEmpty() && accessVal->IsString()) {
735
+ auto accessStr = ConvertFromV8String(isolate, accessVal);
736
+
737
+ if (accessStr == "write-only") {
738
+ access = CanvasStorageTextureAccessWriteOnly;
739
+ } else if (accessStr == "read-only") {
740
+ access = CanvasStorageTextureAccessReadOnly;
741
+ } else if (accessStr == "read-write") {
742
+ access = CanvasStorageTextureAccessReadWrite;
743
+ }
744
+ }
745
+
746
+
747
+ CanvasTextureViewDimension view_dimension = CanvasTextureViewDimensionD2;
748
+
749
+
750
+ v8::Local<v8::Value> viewDimensionVal;
751
+
752
+ storageTextureObj->Get(context,
753
+ ConvertToV8String(isolate, "viewDimension")).ToLocal(
754
+ &viewDimensionVal);
755
+
756
+
757
+ if (!viewDimensionVal.IsEmpty() && viewDimensionVal->IsString()) {
758
+ auto viewDimensionStr = ConvertFromV8String(isolate, viewDimensionVal);
759
+ if (viewDimensionStr == "1d") {
760
+ view_dimension = CanvasTextureViewDimensionD1;
761
+ } else if (viewDimensionStr == "2d") {
762
+ view_dimension = CanvasTextureViewDimensionD2;
763
+ } else if (viewDimensionStr == "2d-array") {
764
+ view_dimension = CanvasTextureViewDimensionD2Array;
765
+ } else if (viewDimensionStr == "cube") {
766
+ view_dimension = CanvasTextureViewDimensionCube;
767
+ } else if (viewDimensionStr == "cube-array") {
768
+ view_dimension = CanvasTextureViewDimensionCubeArray;
769
+ } else if (viewDimensionStr == "3d") {
770
+ view_dimension = CanvasTextureViewDimensionD3;
771
+ }
772
+ }
773
+
774
+
775
+ v8::Local<v8::Value> formatVal;
776
+
777
+ storageTextureObj->Get(context,
778
+ ConvertToV8String(isolate, "format")).ToLocal(
779
+ &formatVal);
780
+
781
+
782
+ if (!formatVal.IsEmpty() && formatVal->IsString()) {
783
+ auto formatStr = ConvertFromV8String(isolate, formatVal);
784
+ auto textureFormat = canvas_native_webgpu_enum_string_to_gpu_texture(
785
+ formatStr.c_str());
786
+ if (textureFormat.tag == CanvasOptionalGPUTextureFormatSome) {
787
+ storage.storage_texture = CanvasStorageTextureBindingLayout{
788
+ access,
789
+ textureFormat.some,
790
+ view_dimension
791
+ };
792
+
793
+ CanvasBindGroupLayoutEntry entry{
794
+ binding,
795
+ visibility,
796
+ storage
797
+ };
798
+
799
+ entries.push_back(entry);
800
+
801
+ continue;
802
+
803
+ } else {
804
+ // todo throw ??
805
+ continue;
806
+ }
807
+ }
808
+
809
+
810
+ }
811
+
812
+
813
+ v8::Local<v8::Value> textureVal;
814
+
815
+ entryObj->Get(context, ConvertToV8String(isolate, "texture")).ToLocal(
816
+ &textureVal);
817
+
818
+ if (!textureVal.IsEmpty() && textureVal->IsObject()) {
819
+ auto textureObj = textureVal.As<v8::Object>();
820
+ bool multisampled = false;
821
+
822
+ v8::Local<v8::Value> multisampledVal;
823
+
824
+ textureObj->Get(context,
825
+ ConvertToV8String(isolate, "multisampled")).ToLocal(
826
+ &multisampledVal);
827
+
828
+ if (!multisampledVal.IsEmpty() && multisampledVal->IsBoolean()) {
829
+ multisampled = multisampledVal->BooleanValue(isolate);
830
+ }
831
+
832
+
833
+ v8::Local<v8::Value> sampleTypeVal;
834
+ textureObj->Get(context, ConvertToV8String(isolate, "sampleType")).ToLocal(
835
+ &sampleTypeVal);
836
+
837
+ CanvasTextureSampleType type = CanvasTextureSampleTypeFloat;
838
+
839
+ if (!sampleTypeVal.IsEmpty() && sampleTypeVal->IsString()) {
840
+ auto typeStr = ConvertFromV8String(isolate, sampleTypeVal);
841
+ if (typeStr == "depth") {
842
+ type = CanvasTextureSampleTypeDepth;
843
+ } else if (typeStr == "float") {
844
+ type = CanvasTextureSampleTypeFloat;
845
+ } else if (typeStr == "sint") {
846
+ type = CanvasTextureSampleTypeSint;
847
+ } else if (typeStr == "uint") {
848
+ type = CanvasTextureSampleTypeUint;
849
+ } else if (typeStr == "unfilterable-float") {
850
+ type = CanvasTextureSampleTypeUnfilterableFloat;
851
+ }
852
+ }
853
+
854
+
855
+ CanvasTextureViewDimension view_dimension = CanvasTextureViewDimensionD2;
856
+
857
+
858
+ v8::Local<v8::Value> viewDimensionVal;
859
+
860
+ textureObj->Get(context,
861
+ ConvertToV8String(isolate, "viewDimension")).ToLocal(
862
+ &viewDimensionVal);
863
+
864
+
865
+ if (!viewDimensionVal.IsEmpty() && viewDimensionVal->IsString()) {
866
+ auto viewDimensionStr = ConvertFromV8String(isolate, viewDimensionVal);
867
+ if (viewDimensionStr == "1d") {
868
+ view_dimension = CanvasTextureViewDimensionD1;
869
+ } else if (viewDimensionStr == "2d") {
870
+ view_dimension = CanvasTextureViewDimensionD2;
871
+ } else if (viewDimensionStr == "2d-array") {
872
+ view_dimension = CanvasTextureViewDimensionD2Array;
873
+ } else if (viewDimensionStr == "cube") {
874
+ view_dimension = CanvasTextureViewDimensionCube;
875
+ } else if (viewDimensionStr == "cube-array") {
876
+ view_dimension = CanvasTextureViewDimensionCubeArray;
877
+ } else if (viewDimensionStr == "3d") {
878
+ view_dimension = CanvasTextureViewDimensionD3;
879
+ }
880
+ }
881
+
882
+
883
+ CanvasBindingType texture{
884
+ CanvasBindingTypeTexture
885
+ };
886
+
887
+ texture.texture = CanvasTextureBindingLayout{
888
+ type,
889
+ view_dimension,
890
+ multisampled
891
+ };
892
+
893
+
894
+ CanvasBindGroupLayoutEntry entry{
895
+ binding,
896
+ visibility,
897
+ texture
898
+ };
899
+
900
+ entries.push_back(entry);
901
+
902
+ continue;
903
+
904
+ }
905
+
906
+ }
907
+ }
908
+ }
909
+
910
+
911
+ auto bind_group = canvas_native_webgpu_device_create_bind_group_layout(ptr->GetGPUDevice(),
912
+ label,
913
+ entries.data(),
914
+ entries.size());
915
+
916
+ if (bind_group != nullptr) {
917
+ auto ret = GPUBindGroupLayoutImpl::NewInstance(isolate,
918
+ new GPUBindGroupLayoutImpl(bind_group));
919
+ args.GetReturnValue().Set(ret);
920
+ return;
921
+ }
922
+ }
923
+
924
+ args.GetReturnValue().SetUndefined();
925
+ }
926
+
927
+ void GPUDeviceImpl::CreateBuffer(const v8::FunctionCallbackInfo<v8::Value> &args) {
928
+ GPUDeviceImpl *ptr = GetPointer(args.This());
929
+ if (ptr == nullptr) {
930
+ return;
931
+ }
932
+ auto isolate = args.GetIsolate();
933
+ auto context = isolate->GetCurrentContext();
934
+ char *label = nullptr;
935
+ bool mappedAtCreation = false;
936
+ uint64_t size = 0;
937
+ uint32_t usage = 0;
938
+
939
+ auto optionsVal = args[0];
940
+
941
+ if (optionsVal->IsObject()) {
942
+ auto options = optionsVal.As<v8::Object>();
943
+ v8::Local<v8::Value> labelVal;
944
+ options->Get(context, ConvertToV8String(isolate, "label")).ToLocal(&labelVal);
945
+
946
+ if (!labelVal.IsEmpty() && labelVal->IsString()) {
947
+ label = *v8::String::Utf8Value(isolate, labelVal);
948
+ }
949
+
950
+ v8::Local<v8::Value> mappedAtCreationVal;
951
+
952
+ options->Get(context, ConvertToV8String(isolate, "mappedAtCreation")).ToLocal(
953
+ &mappedAtCreationVal);
954
+
955
+ if (!mappedAtCreationVal.IsEmpty()) {
956
+ mappedAtCreation = mappedAtCreationVal->BooleanValue(isolate);
957
+ }
958
+
959
+ v8::Local<v8::Value> sizeVal;
960
+ options->Get(context, ConvertToV8String(isolate, "size")).ToLocal(&sizeVal);
961
+
962
+ if (sizeVal->IsNumber()) {
963
+ size = (uint64_t) sizeVal->NumberValue(context).ToChecked();
964
+ }
965
+
966
+
967
+ v8::Local<v8::Value> usageVal;
968
+ options->Get(context, ConvertToV8String(isolate, "usage")).ToLocal(&usageVal);
969
+
970
+ if (usageVal->IsNumber()) {
971
+ usage = usageVal->Uint32Value(context).ToChecked();
972
+ }
973
+ }
974
+
975
+ auto buffer = canvas_native_webgpu_device_create_buffer(ptr->GetGPUDevice(), label, size, usage,
976
+ mappedAtCreation);
977
+
978
+ if (buffer != nullptr) {
979
+ auto bufImpl = new GPUBufferImpl(buffer);
980
+ auto ret = GPUBufferImpl::NewInstance(isolate, bufImpl);
981
+ args.GetReturnValue().Set(ret);
982
+
983
+ } else {
984
+ // todo return invalid buffer
985
+ args.GetReturnValue().SetUndefined();
986
+ }
987
+ }
988
+
989
+ void GPUDeviceImpl::CreateCommandEncoder(const v8::FunctionCallbackInfo<v8::Value> &args) {
990
+ GPUDeviceImpl *ptr = GetPointer(args.This());
991
+ if (ptr == nullptr) {
992
+ return;
993
+ }
994
+ auto isolate = args.GetIsolate();
995
+
996
+ char *label = nullptr;
997
+
998
+ auto labelVal = args[0];
999
+
1000
+ if (!labelVal.IsEmpty() && labelVal->IsString()) {
1001
+ label = *v8::String::Utf8Value(isolate, labelVal);
1002
+ }
1003
+
1004
+ auto encoder = canvas_native_webgpu_device_create_command_encoder(ptr->GetGPUDevice(), label);
1005
+
1006
+ if (encoder != nullptr) {
1007
+ auto instance = new GPUCommandEncoderImpl(encoder);
1008
+ auto ret = GPUCommandEncoderImpl::NewInstance(isolate, instance);
1009
+ args.GetReturnValue().Set(ret);
1010
+ return;
1011
+ }
1012
+
1013
+ args.GetReturnValue().SetUndefined();
1014
+
1015
+ }
1016
+
1017
+ void GPUDeviceImpl::CreateComputePipeline(const v8::FunctionCallbackInfo<v8::Value> &args) {
1018
+ GPUDeviceImpl *ptr = GetPointer(args.This());
1019
+ if (ptr == nullptr) {
1020
+ return;
1021
+ }
1022
+ auto isolate = args.GetIsolate();
1023
+ auto context = isolate->GetCurrentContext();
1024
+
1025
+ auto optionsVal = args[0];
1026
+
1027
+ if (!optionsVal->IsObject()) {
1028
+ // should error at this point
1029
+ return;
1030
+ }
1031
+ auto options = optionsVal.As<v8::Object>();
1032
+
1033
+ v8::Local<v8::Value> labelVal;
1034
+ options->Get(context, ConvertToV8String(isolate, "label")).ToLocal(&labelVal);
1035
+
1036
+ char *label = nullptr;
1037
+
1038
+ if (!labelVal.IsEmpty() && labelVal->IsString()) {
1039
+ label = *v8::String::Utf8Value(isolate, labelVal);
1040
+ }
1041
+
1042
+ CanvasGPUPipelineLayoutOrGPUAutoLayoutMode layout{
1043
+ CanvasGPUPipelineLayoutOrGPUAutoLayoutModeAuto
1044
+ };
1045
+
1046
+ v8::Local<v8::Value> layoutVal;
1047
+ options->Get(context, ConvertToV8String(isolate, "layout")).ToLocal(&layoutVal);
1048
+
1049
+ if (!layoutVal.IsEmpty() && layoutVal->IsObject()) {
1050
+ auto layoutImpl = GPUPipelineLayoutImpl::GetPointer(layoutVal.As<v8::Object>());
1051
+ if (layoutImpl != nullptr) {
1052
+ layout.tag = CanvasGPUPipelineLayoutOrGPUAutoLayoutModeLayout;
1053
+ layout.layout = layoutImpl->GetPipeline();
1054
+ }
1055
+ }
1056
+
1057
+
1058
+ v8::Local<v8::Value> computeVal;
1059
+ options->Get(context, ConvertToV8String(isolate, "compute")).ToLocal(&computeVal);
1060
+
1061
+ if (!computeVal.IsEmpty() && computeVal->IsObject()) {
1062
+
1063
+ auto computeObj = computeVal.As<v8::Object>();
1064
+
1065
+ v8::Local<v8::Value> constantsVal;
1066
+ computeObj->Get(context, ConvertToV8String(isolate, "constants")).ToLocal(
1067
+ &constantsVal);
1068
+
1069
+ CanvasConstants *store = nullptr;
1070
+
1071
+ if (!constantsVal.IsEmpty() && constantsVal->IsMap()) {
1072
+ auto constants = constantsVal.As<v8::Map>();
1073
+ auto keyValues = constants->AsArray();
1074
+ auto length = keyValues->Length();
1075
+ if (length > 0) {
1076
+ store = canvas_native_webgpu_constants_create();
1077
+ for (int i = 0; i < length; i += 2) {
1078
+ auto k = i;
1079
+ auto v = k + 1;
1080
+
1081
+ v8::Local<v8::Value> keyVal;
1082
+ keyValues->Get(context, k).ToLocal(&keyVal);
1083
+ v8::Local<v8::Value> valueVal;
1084
+ keyValues->Get(context, v).ToLocal(&valueVal);
1085
+
1086
+
1087
+ if (!keyVal.IsEmpty() && keyVal->IsString() && !valueVal.IsEmpty() &&
1088
+ valueVal->IsNumber()) {
1089
+ canvas_native_webgpu_constants_insert(
1090
+ store,
1091
+ *v8::String::Utf8Value(isolate, keyVal),
1092
+ valueVal.As<v8::Number>()->Value()
1093
+ );
1094
+ }
1095
+
1096
+ }
1097
+ }
1098
+ }
1099
+
1100
+
1101
+ v8::Local<v8::Value> entryPoint;
1102
+ computeObj->Get(context, ConvertToV8String(isolate, "entryPoint")).ToLocal(
1103
+ &entryPoint);
1104
+
1105
+ char *entry_point = nullptr;
1106
+
1107
+ if (!entryPoint.IsEmpty() && entryPoint->IsString()) {
1108
+ auto ep = v8::String::Utf8Value(isolate, entryPoint);
1109
+ entry_point = (char *) malloc(ep.length());
1110
+ std::strcpy(entry_point, *ep);
1111
+ }
1112
+
1113
+ v8::Local<v8::Value> moduleVal;
1114
+ computeObj->Get(context, ConvertToV8String(isolate, "module")).ToLocal(&moduleVal);
1115
+
1116
+ auto module = GPUShaderModuleImpl::GetPointer(moduleVal.As<v8::Object>());
1117
+
1118
+ CanvasProgrammableStage stage{
1119
+ module->GetShaderModule(),
1120
+ entry_point,
1121
+ store
1122
+ };
1123
+
1124
+ auto pipeline = canvas_native_webgpu_device_create_compute_pipeline(ptr->GetGPUDevice(),
1125
+ label, layout, &stage);
1126
+
1127
+ if (entry_point != nullptr) {
1128
+ free(entry_point);
1129
+ }
1130
+
1131
+ if (store != nullptr) {
1132
+ canvas_native_webgpu_constants_destroy(store);
1133
+ }
1134
+
1135
+ if (pipeline != nullptr) {
1136
+ auto ret = GPUComputePipelineImpl::NewInstance(isolate,
1137
+ new GPUComputePipelineImpl(pipeline));
1138
+ args.GetReturnValue().Set(ret);
1139
+ return;
1140
+ }
1141
+
1142
+
1143
+ }
1144
+
1145
+ args.GetReturnValue().SetUndefined();
1146
+ }
1147
+
1148
+ void GPUDeviceImpl::CreatePipelineLayout(const v8::FunctionCallbackInfo<v8::Value> &args) {
1149
+ GPUDeviceImpl *ptr = GetPointer(args.This());
1150
+ if (ptr == nullptr) {
1151
+ return;
1152
+ }
1153
+ auto isolate = args.GetIsolate();
1154
+ auto context = isolate->GetCurrentContext();
1155
+
1156
+ auto optionsVal = args[0];
1157
+
1158
+ if (!optionsVal->IsObject()) {
1159
+ // should error at this point
1160
+ return;
1161
+ }
1162
+ auto options = optionsVal.As<v8::Object>();
1163
+
1164
+ v8::Local<v8::Value> labelVal;
1165
+ options->Get(context, ConvertToV8String(isolate, "label")).ToLocal(&labelVal);
1166
+
1167
+ char *label = nullptr;
1168
+
1169
+ if (!labelVal.IsEmpty() && labelVal->IsString()) {
1170
+ label = *v8::String::Utf8Value(isolate, labelVal);
1171
+ }
1172
+
1173
+
1174
+ std::vector<const CanvasGPUBindGroupLayout *> group_layouts;
1175
+
1176
+ v8::Local<v8::Value> groupLayoutsVal;
1177
+ options->Get(context, ConvertToV8String(isolate, "bindGroupLayouts")).ToLocal(&groupLayoutsVal);
1178
+
1179
+ if (!groupLayoutsVal.IsEmpty() && groupLayoutsVal->IsArray()) {
1180
+ auto groupLayoutsArray = groupLayoutsVal.As<v8::Array>();
1181
+ auto len = groupLayoutsArray->Length();
1182
+ for (int i = 0; i < len; i++) {
1183
+ v8::Local<v8::Value> groupVal;
1184
+ groupLayoutsArray->Get(context, i).ToLocal(&groupVal);
1185
+ if (GetNativeType(groupVal) == NativeType::GPUBindGroupLayout) {
1186
+ auto layout = GPUBindGroupLayoutImpl::GetPointer(groupVal.As<v8::Object>());
1187
+ if (layout != nullptr) {
1188
+ group_layouts.push_back(layout->GetBindGroupLayout());
1189
+ }
1190
+ }
1191
+ }
1192
+
1193
+ auto layout = canvas_native_webgpu_device_create_pipeline_layout(ptr->GetGPUDevice(), label,
1194
+ group_layouts.data(),
1195
+ group_layouts.size());
1196
+
1197
+ if (layout != nullptr) {
1198
+ auto ret = GPUPipelineLayoutImpl::NewInstance(isolate,
1199
+ new GPUPipelineLayoutImpl(layout));
1200
+ args.GetReturnValue().Set(ret);
1201
+ return;
1202
+ }
1203
+ }
1204
+
1205
+
1206
+ args.GetReturnValue().SetUndefined();
1207
+ }
1208
+
1209
+ void GPUDeviceImpl::CreateQuerySet(const v8::FunctionCallbackInfo<v8::Value> &args) {
1210
+ GPUDeviceImpl *ptr = GetPointer(args.This());
1211
+ if (ptr == nullptr) {
1212
+ return;
1213
+ }
1214
+ auto isolate = args.GetIsolate();
1215
+ auto context = isolate->GetCurrentContext();
1216
+
1217
+ auto optionsVal = args[0];
1218
+
1219
+ if (!optionsVal->IsObject()) {
1220
+ // should error at this point
1221
+ return;
1222
+ }
1223
+ auto options = optionsVal.As<v8::Object>();
1224
+
1225
+ v8::Local<v8::Value> labelVal;
1226
+ options->Get(context, ConvertToV8String(isolate, "label")).ToLocal(&labelVal);
1227
+
1228
+ char *label = nullptr;
1229
+
1230
+ if (!labelVal.IsEmpty() && labelVal->IsString()) {
1231
+ label = *v8::String::Utf8Value(isolate, labelVal);
1232
+ }
1233
+
1234
+
1235
+ v8::Local<v8::Value> typeVal;
1236
+ options->Get(context, ConvertToV8String(isolate, "type")).ToLocal(&labelVal);
1237
+
1238
+
1239
+ v8::Local<v8::Value> countVal;
1240
+ options->Get(context, ConvertToV8String(isolate, "count")).ToLocal(&labelVal);
1241
+
1242
+ auto typeStr = ConvertFromV8String(isolate, typeVal);
1243
+
1244
+ const CanvasGPUQuerySet *query_set = nullptr;
1245
+ if (typeStr == "occlusion") {
1246
+ query_set = canvas_native_webgpu_device_create_query_set(ptr->GetGPUDevice(), label,
1247
+ CanvasQueryTypeOcclusion,
1248
+ countVal->Uint32Value(
1249
+ context).FromJust());
1250
+ } else if (typeStr == "timestamp") {
1251
+ query_set = canvas_native_webgpu_device_create_query_set(ptr->GetGPUDevice(), label,
1252
+ CanvasQueryTypeTimestamp,
1253
+ countVal->Uint32Value(
1254
+ context).FromJust());
1255
+ } else {
1256
+ // todo throw
1257
+ }
1258
+
1259
+
1260
+ if (query_set != nullptr) {
1261
+ auto ret = GPUQuerySetImpl::NewInstance(isolate, new GPUQuerySetImpl(query_set));
1262
+ args.GetReturnValue().Set(ret);
1263
+ return;
1264
+ }
1265
+
1266
+ args.GetReturnValue().SetUndefined();
1267
+
1268
+ }
1269
+
1270
+ void GPUDeviceImpl::CreateRenderBundleEncoder(const v8::FunctionCallbackInfo<v8::Value> &args) {
1271
+ GPUDeviceImpl *ptr = GetPointer(args.This());
1272
+ if (ptr == nullptr) {
1273
+ return;
1274
+ }
1275
+ auto isolate = args.GetIsolate();
1276
+ auto context = isolate->GetCurrentContext();
1277
+
1278
+ auto optionsVal = args[0];
1279
+
1280
+ if (!optionsVal->IsObject()) {
1281
+ // should error at this point
1282
+ return;
1283
+ }
1284
+ auto options = optionsVal.As<v8::Object>();
1285
+
1286
+ v8::Local<v8::Value> labelVal;
1287
+ options->Get(context, ConvertToV8String(isolate, "label")).ToLocal(&labelVal);
1288
+
1289
+ char *label = nullptr;
1290
+
1291
+ if (!labelVal.IsEmpty() && labelVal->IsString()) {
1292
+ label = *v8::String::Utf8Value(isolate, labelVal);
1293
+ }
1294
+
1295
+
1296
+ std::vector<CanvasGPUTextureFormat> colorFormats;
1297
+
1298
+ v8::Local<v8::Value> colorFormatsVal;
1299
+ options->Get(context, ConvertToV8String(isolate, "colorFormats")).ToLocal(&colorFormatsVal);
1300
+
1301
+ if (!colorFormatsVal.IsEmpty() && colorFormatsVal->IsArray()) {
1302
+ auto colorFormatsArray = colorFormatsVal.As<v8::Array>();
1303
+ auto len = colorFormatsArray->Length();
1304
+ for (int i = 0; i < len; i++) {
1305
+ v8::Local<v8::Value> formatVal;
1306
+ colorFormatsArray->Get(context, i).ToLocal(&formatVal);
1307
+ if (!formatVal.IsEmpty() && formatVal->IsString()) {
1308
+ auto formatStr = ConvertFromV8String(isolate, formatVal);
1309
+ auto format = canvas_native_webgpu_enum_string_to_gpu_texture(formatStr.c_str());
1310
+ if (format.tag == CanvasOptionalGPUTextureFormatSome) {
1311
+ colorFormats.push_back(format.some);
1312
+ }
1313
+ }
1314
+
1315
+ }
1316
+ }
1317
+
1318
+
1319
+ auto depthStencilFormat = CanvasOptionalGPUTextureFormat{
1320
+ CanvasOptionalGPUTextureFormatNone
1321
+ };
1322
+
1323
+ v8::Local<v8::Value> depthStencilFormatVal;
1324
+ options->Get(context, ConvertToV8String(isolate, "depthStencilFormat")).ToLocal(
1325
+ &depthStencilFormatVal);
1326
+
1327
+ if (!depthStencilFormatVal.IsEmpty() && depthStencilFormatVal->IsString()) {
1328
+ auto depthStencilFormatStr = ConvertFromV8String(isolate, depthStencilFormatVal);
1329
+ depthStencilFormat = canvas_native_webgpu_enum_string_to_gpu_texture(
1330
+ depthStencilFormatStr.c_str());
1331
+ }
1332
+
1333
+ uint32_t sampleCount = 1;
1334
+
1335
+ bool depthReadOnly = false;
1336
+
1337
+ bool stencilReadOnly = false;
1338
+
1339
+ CanvasCreateRenderBundleEncoderDescriptor descriptor{
1340
+ label,
1341
+ colorFormats.data(),
1342
+ colorFormats.size(),
1343
+ depthStencilFormat,
1344
+ sampleCount,
1345
+ depthReadOnly,
1346
+ stencilReadOnly
1347
+ };
1348
+
1349
+
1350
+ auto encoder = canvas_native_webgpu_device_create_render_bundle_encoder(ptr->GetGPUDevice(),
1351
+ &descriptor);
1352
+
1353
+ if (encoder != nullptr) {
1354
+ auto ret = GPURenderBundleEncoderImpl::NewInstance(isolate,
1355
+ new GPURenderBundleEncoderImpl(encoder));
1356
+ args.GetReturnValue().Set(ret);
1357
+ return;
1358
+ }
1359
+
1360
+ args.GetReturnValue().SetUndefined();
1361
+ }
1362
+
1363
+ void GPUDeviceImpl::CreateRenderPipeline(const v8::FunctionCallbackInfo<v8::Value> &args) {
1364
+ GPUDeviceImpl *ptr = GetPointer(args.This());
1365
+ if (ptr == nullptr) {
1366
+ return;
1367
+ }
1368
+ auto isolate = args.GetIsolate();
1369
+ auto context = isolate->GetCurrentContext();
1370
+
1371
+ CanvasCreateRenderPipelineDescriptor descriptor{};
1372
+ descriptor.label = nullptr;
1373
+
1374
+ auto optionsVal = args[0];
1375
+
1376
+ if (!optionsVal->IsObject()) {
1377
+ // should error at this point
1378
+ return;
1379
+ }
1380
+ auto options = optionsVal.As<v8::Object>();
1381
+
1382
+
1383
+ v8::Local<v8::Value> stencilValue;
1384
+ options->Get(context, ConvertToV8String(isolate, "depthStencil")).ToLocal(
1385
+ &stencilValue);
1386
+
1387
+ CanvasDepthStencilState *stencil = nullptr;
1388
+
1389
+ if (!stencilValue.IsEmpty() && stencilValue->IsObject()) {
1390
+ auto stencilObj = stencilValue.As<v8::Object>();
1391
+ stencil = new CanvasDepthStencilState{};
1392
+ stencil->depth_bias = 0;
1393
+ stencil->depth_bias_clamp = 0;
1394
+ stencil->depth_bias_slope_scale = 0;
1395
+ stencil->stencil_read_mask = 0xFFFFFFFF;
1396
+ stencil->stencil_write_mask = 0xFFFFFFFF;
1397
+ stencil->stencil_front = CanvasStencilFaceState{
1398
+ CanvasCompareFunctionAlways,
1399
+ CanvasStencilOperationKeep,
1400
+ CanvasStencilOperationKeep,
1401
+ CanvasStencilOperationKeep
1402
+ };
1403
+
1404
+ stencil->stencil_back = CanvasStencilFaceState{
1405
+ CanvasCompareFunctionAlways,
1406
+ CanvasStencilOperationKeep,
1407
+ CanvasStencilOperationKeep,
1408
+ CanvasStencilOperationKeep
1409
+ };
1410
+ // todo throw if failed
1411
+ v8::Local<v8::Value> formatValue;
1412
+
1413
+ stencilObj->Get(context, ConvertToV8String(isolate, "format")).ToLocal(&formatValue);
1414
+ if (!formatValue.IsEmpty() && formatValue->IsString()) {
1415
+ auto val = *v8::String::Utf8Value(isolate, formatValue);
1416
+ auto format = canvas_native_webgpu_enum_string_to_gpu_texture(
1417
+ val);
1418
+ if (format.tag ==
1419
+ CanvasOptionalGPUTextureFormat_Tag::CanvasOptionalGPUTextureFormatSome) {
1420
+ stencil->format = format.some;
1421
+ }
1422
+ } else {
1423
+ // todo throw
1424
+ }
1425
+
1426
+ v8::Local<v8::Value> depthBiasVal;
1427
+ stencilObj->Get(context, ConvertToV8String(isolate, "depthBias")).ToLocal(&depthBiasVal);
1428
+
1429
+ if (!depthBiasVal.IsEmpty() && depthBiasVal->IsInt32()) {
1430
+ stencil->depth_bias = depthBiasVal->Int32Value(context).FromJust();
1431
+ }
1432
+
1433
+ v8::Local<v8::Value> depthBiasClampVal;
1434
+ stencilObj->Get(context, ConvertToV8String(isolate, "depthBiasClamp")).ToLocal(
1435
+ &depthBiasClampVal);
1436
+
1437
+ if (!depthBiasClampVal.IsEmpty() && depthBiasClampVal->IsInt32()) {
1438
+ stencil->depth_bias_clamp = depthBiasClampVal->Int32Value(context).FromJust();
1439
+ }
1440
+
1441
+
1442
+ v8::Local<v8::Value> depthBiasSlopeScaleVal;
1443
+ stencilObj->Get(context, ConvertToV8String(isolate, "depthBiasSlopeScale")).ToLocal(
1444
+ &depthBiasSlopeScaleVal);
1445
+
1446
+ if (!depthBiasSlopeScaleVal.IsEmpty() && depthBiasSlopeScaleVal->IsInt32()) {
1447
+ stencil->depth_bias_slope_scale = depthBiasSlopeScaleVal->Int32Value(
1448
+ context).FromJust();
1449
+ }
1450
+
1451
+ v8::Local<v8::Value> depthCompareVal;
1452
+ stencilObj->Get(context, ConvertToV8String(isolate, "depthCompare")).ToLocal(
1453
+ &depthCompareVal);
1454
+
1455
+ auto depthCompareStr = ConvertFromV8String(isolate, depthCompareVal);
1456
+
1457
+ if (depthCompareStr == "never") {
1458
+ stencil->depth_compare = CanvasCompareFunctionNever;
1459
+ } else if (depthCompareStr == "less") {
1460
+ stencil->depth_compare = CanvasCompareFunctionLess;
1461
+ } else if (depthCompareStr == "equal") {
1462
+ stencil->depth_compare = CanvasCompareFunctionEqual;
1463
+ } else if (depthCompareStr == "less-equal") {
1464
+ stencil->depth_compare = CanvasCompareFunctionLessEqual;
1465
+ } else if (depthCompareStr == "greater") {
1466
+ stencil->depth_compare = CanvasCompareFunctionGreater;
1467
+ } else if (depthCompareStr == "not-equal") {
1468
+ stencil->depth_compare = CanvasCompareFunctionNotEqual;
1469
+ } else if (depthCompareStr == "greater-equal") {
1470
+ stencil->depth_compare = CanvasCompareFunctionGreaterEqual;
1471
+ } else if (depthCompareStr == "always") {
1472
+ stencil->depth_compare = CanvasCompareFunctionAlways;
1473
+ }
1474
+
1475
+ stencil->depth_write_enabled = stencilObj->Get(context, ConvertToV8String(isolate,
1476
+ "depthWriteEnabled")).ToLocalChecked()->BooleanValue(
1477
+ isolate);
1478
+
1479
+
1480
+ v8::Local<v8::Value> stencilBackVal;
1481
+ stencilObj->Get(context, ConvertToV8String(isolate, "stencilBack")).ToLocal(
1482
+ &stencilBackVal);
1483
+
1484
+ if (!stencilBackVal.IsEmpty() && stencilBackVal->IsObject()) {
1485
+ auto stencilBackObj = stencilBackVal.As<v8::Object>();
1486
+
1487
+ v8::Local<v8::Value> compareVal;
1488
+ stencilBackObj->Get(context, ConvertToV8String(isolate, "compare")).ToLocal(
1489
+ &compareVal);
1490
+
1491
+ stencil->stencil_back.compare = ParseCompareFunction(isolate, compareVal,
1492
+ stencil->stencil_back.compare);
1493
+
1494
+ v8::Local<v8::Value> depthFailOpVal;
1495
+ stencilBackObj->Get(context, ConvertToV8String(isolate, "depthFailOp")).ToLocal(
1496
+ &depthFailOpVal);
1497
+
1498
+ stencil->stencil_back.depth_fail_op = ParseStencilOperation(isolate, depthFailOpVal,
1499
+ stencil->stencil_back.depth_fail_op);
1500
+
1501
+
1502
+ v8::Local<v8::Value> failOpVal;
1503
+ stencilBackObj->Get(context, ConvertToV8String(isolate, "failOp")).ToLocal(
1504
+ &failOpVal);
1505
+
1506
+ stencil->stencil_back.fail_op = ParseStencilOperation(isolate, failOpVal,
1507
+ stencil->stencil_back.fail_op);
1508
+
1509
+ v8::Local<v8::Value> passOpVal;
1510
+ stencilBackObj->Get(context, ConvertToV8String(isolate, "passOp")).ToLocal(
1511
+ &passOpVal);
1512
+
1513
+ stencil->stencil_back.pass_op = ParseStencilOperation(isolate, passOpVal,
1514
+ stencil->stencil_back.pass_op);
1515
+
1516
+ }
1517
+
1518
+
1519
+ v8::Local<v8::Value> stencilFrontVal;
1520
+ stencilObj->Get(context, ConvertToV8String(isolate, "stencilFront")).ToLocal(
1521
+ &stencilFrontVal);
1522
+
1523
+ if (!stencilFrontVal.IsEmpty() && stencilFrontVal->IsObject()) {
1524
+ auto stencilFrontObj = stencilFrontVal.As<v8::Object>();
1525
+
1526
+ v8::Local<v8::Value> compareVal;
1527
+ stencilFrontObj->Get(context, ConvertToV8String(isolate, "compare")).ToLocal(
1528
+ &compareVal);
1529
+
1530
+ stencil->stencil_front.compare = ParseCompareFunction(isolate, compareVal,
1531
+ stencil->stencil_front.compare);
1532
+
1533
+ v8::Local<v8::Value> depthFailOpVal;
1534
+ stencilFrontObj->Get(context, ConvertToV8String(isolate, "depthFailOp")).ToLocal(
1535
+ &depthFailOpVal);
1536
+
1537
+ stencil->stencil_front.depth_fail_op = ParseStencilOperation(isolate, depthFailOpVal,
1538
+ stencil->stencil_front.depth_fail_op);
1539
+
1540
+
1541
+ v8::Local<v8::Value> failOpVal;
1542
+ stencilFrontObj->Get(context, ConvertToV8String(isolate, "failOp")).ToLocal(
1543
+ &failOpVal);
1544
+
1545
+ stencil->stencil_front.fail_op = ParseStencilOperation(isolate, failOpVal,
1546
+ stencil->stencil_front.fail_op);
1547
+
1548
+ v8::Local<v8::Value> passOpVal;
1549
+ stencilFrontObj->Get(context, ConvertToV8String(isolate, "passOp")).ToLocal(
1550
+ &passOpVal);
1551
+
1552
+ stencil->stencil_front.pass_op = ParseStencilOperation(isolate, passOpVal,
1553
+ stencil->stencil_front.pass_op);
1554
+
1555
+ }
1556
+
1557
+ v8::Local<v8::Value> stencilReadMaskVal;
1558
+ stencilObj->Get(context, ConvertToV8String(isolate, "stencilReadMask")).ToLocal(
1559
+ &stencilReadMaskVal);
1560
+
1561
+ if (!stencilReadMaskVal.IsEmpty() && stencilReadMaskVal->IsUint32()) {
1562
+ stencil->stencil_read_mask = stencilReadMaskVal->Uint32Value(context).FromJust();
1563
+ }
1564
+
1565
+
1566
+ v8::Local<v8::Value> stencilWriteMaskVal;
1567
+ stencilObj->Get(context, ConvertToV8String(isolate, "stencilWriteMask")).ToLocal(
1568
+ &stencilWriteMaskVal);
1569
+
1570
+ if (!stencilWriteMaskVal.IsEmpty() && stencilWriteMaskVal->IsUint32()) {
1571
+ stencil->stencil_write_mask = stencilWriteMaskVal->Uint32Value(context).FromJust();
1572
+ }
1573
+
1574
+ }
1575
+
1576
+
1577
+ v8::Local<v8::Value> fragmentValue;
1578
+ options->Get(context, ConvertToV8String(isolate, "fragment")).ToLocal(
1579
+ &fragmentValue);
1580
+
1581
+ CanvasFragmentState *fragment = nullptr;
1582
+
1583
+ std::vector<CanvasColorTargetState> targets;
1584
+
1585
+ if (!fragmentValue.IsEmpty() && fragmentValue->IsObject()) {
1586
+ auto fragmentValueObj = fragmentValue.As<v8::Object>();
1587
+ fragment = new CanvasFragmentState{};
1588
+
1589
+ v8::Local<v8::Value> targetsVal;
1590
+ fragmentValueObj->Get(context, ConvertToV8String(isolate, "targets")).ToLocal(&targetsVal);
1591
+
1592
+
1593
+ auto targetsArray = targetsVal.As<v8::Array>();
1594
+ auto len = targetsArray->Length();
1595
+
1596
+ for (int i = 0; i < len; i++) {
1597
+ auto state = targetsArray->Get(context, i).ToLocalChecked().As<v8::Object>();
1598
+
1599
+ auto formatVal = state->Get(context,
1600
+ ConvertToV8String(isolate, "format")).ToLocalChecked();
1601
+ auto formatStr = ConvertFromV8String(isolate, formatVal);
1602
+ auto formatResult = canvas_native_webgpu_enum_string_to_gpu_texture(formatStr.c_str());
1603
+
1604
+
1605
+ if (formatResult.tag == CanvasOptionalGPUTextureFormatNone) {
1606
+ // todo throw
1607
+ args.GetReturnValue().SetUndefined();
1608
+ return;
1609
+ } else {}
1610
+
1611
+ auto format = CanvasGPUTextureFormat{
1612
+ formatResult.some.tag
1613
+ };
1614
+
1615
+ uint32_t writeMask = 0xF;
1616
+
1617
+ v8::Local<v8::Value> writeMaskVal;
1618
+
1619
+ state->Get(context, ConvertToV8String(isolate, "writeMask")).ToLocal(&writeMaskVal);
1620
+
1621
+ if (!writeMaskVal.IsEmpty() && writeMaskVal->IsUint32()) {
1622
+ writeMask = writeMaskVal->Uint32Value(context).FromJust();
1623
+ }
1624
+
1625
+ CanvasOptionalBlendState blend{
1626
+ CanvasOptionalBlendStateNone
1627
+ };
1628
+
1629
+ v8::Local<v8::Value> blendVal;
1630
+
1631
+ state->Get(context, ConvertToV8String(isolate, "blend")).ToLocal(&blendVal);
1632
+
1633
+ if (!blendVal.IsEmpty() && blendVal->IsObject()) {
1634
+ auto blendObj = blendVal.As<v8::Object>();
1635
+ auto alpha = blendObj->Get(context, ConvertToV8String(isolate,
1636
+ "alpha")).ToLocalChecked().As<v8::Object>();
1637
+
1638
+ v8::Local<v8::Value> alphaSrcFactorVal;
1639
+
1640
+ alpha->Get(context,
1641
+ ConvertToV8String(isolate,
1642
+ "srcFactor")).ToLocal(&alphaSrcFactorVal);
1643
+
1644
+ auto alphaSrcFactor = ParseBlendFactor(isolate, alphaSrcFactorVal,
1645
+ CanvasBlendFactorZero);
1646
+
1647
+ v8::Local<v8::Value> alphaDstFactorVal;
1648
+ alpha->Get(context,
1649
+ ConvertToV8String(isolate,
1650
+ "dstFactor")).ToLocal(&alphaDstFactorVal);
1651
+
1652
+ auto alphaDstFactor = ParseBlendFactor(isolate, alphaDstFactorVal,
1653
+ CanvasBlendFactorZero);
1654
+
1655
+ v8::Local<v8::Value> alphaOperationVal;
1656
+
1657
+ alpha->Get(context,
1658
+ ConvertToV8String(isolate,
1659
+ "operation")).ToLocal(&alphaOperationVal);
1660
+
1661
+ auto alphaOperation = ParseBlendOperation(isolate, alphaOperationVal,
1662
+ CanvasBlendOperationAdd);
1663
+
1664
+ auto alpha_val = CanvasBlendComponent{alphaSrcFactor, alphaDstFactor,
1665
+ alphaOperation};
1666
+
1667
+ auto color = blendObj->Get(context, ConvertToV8String(isolate,
1668
+ "color")).ToLocalChecked().As<v8::Object>();
1669
+
1670
+
1671
+ v8::Local<v8::Value> colorSrcFactorVal;
1672
+
1673
+ color->Get(context,
1674
+ ConvertToV8String(isolate,
1675
+ "srcFactor")).ToLocal(&colorSrcFactorVal);
1676
+
1677
+ auto colorSrcFactor = ParseBlendFactor(isolate, colorSrcFactorVal,
1678
+ CanvasBlendFactorZero);
1679
+
1680
+ v8::Local<v8::Value> colorDstFactorVal;
1681
+ color->Get(context,
1682
+ ConvertToV8String(isolate,
1683
+ "dstFactor")).ToLocal(&colorDstFactorVal);
1684
+
1685
+ auto colorDstFactor = ParseBlendFactor(isolate, colorDstFactorVal,
1686
+ CanvasBlendFactorZero);
1687
+
1688
+ v8::Local<v8::Value> colorOperationVal;
1689
+
1690
+ color->Get(context,
1691
+ ConvertToV8String(isolate,
1692
+ "operation")).ToLocal(&colorOperationVal);
1693
+
1694
+ auto colorOperation = ParseBlendOperation(isolate, colorOperationVal,
1695
+ CanvasBlendOperationAdd);
1696
+
1697
+
1698
+ auto color_val = CanvasBlendComponent{colorSrcFactor, colorDstFactor,
1699
+ colorOperation};
1700
+
1701
+
1702
+ blend = CanvasOptionalBlendState{
1703
+ CanvasOptionalBlendStateSome,
1704
+ CanvasBlendState{
1705
+ color_val, alpha_val
1706
+ }
1707
+ };
1708
+ }
1709
+
1710
+ auto targetState = CanvasColorTargetState{
1711
+ format,
1712
+ blend,
1713
+ writeMask
1714
+ };
1715
+
1716
+ targets.push_back(targetState);
1717
+ }
1718
+
1719
+ if (!targets.empty()) {
1720
+ fragment->targets = targets.data();
1721
+ fragment->targets_size = targets.size();
1722
+ }
1723
+
1724
+ v8::Local<v8::Value> constantsVal;
1725
+ fragmentValueObj->Get(context, ConvertToV8String(isolate, "constants")).ToLocal(
1726
+ &constantsVal);
1727
+
1728
+ if (!constantsVal.IsEmpty() && constantsVal->IsMap()) {
1729
+ auto constants = constantsVal.As<v8::Map>();
1730
+ auto keyValues = constants->AsArray();
1731
+ auto length = keyValues->Length();
1732
+ CanvasConstants *store = nullptr;
1733
+
1734
+ if (length > 0) {
1735
+ store = canvas_native_webgpu_constants_create();
1736
+ for (int i = 0; i < length; i += 2) {
1737
+ auto k = i;
1738
+ auto v = k + 1;
1739
+
1740
+ v8::Local<v8::Value> keyVal;
1741
+ keyValues->Get(context, k).ToLocal(&keyVal);
1742
+ v8::Local<v8::Value> valueVal;
1743
+ keyValues->Get(context, v).ToLocal(&valueVal);
1744
+
1745
+
1746
+ if (!keyVal.IsEmpty() && keyVal->IsString() && !valueVal.IsEmpty() &&
1747
+ valueVal->IsNumber()) {
1748
+ canvas_native_webgpu_constants_insert(
1749
+ store,
1750
+ *v8::String::Utf8Value(isolate, keyVal),
1751
+ valueVal.As<v8::Number>()->Value()
1752
+ );
1753
+ }
1754
+
1755
+ }
1756
+ }
1757
+ fragment->constants = store;
1758
+ }
1759
+
1760
+
1761
+ v8::Local<v8::Value> entryPoint;
1762
+ fragmentValueObj->Get(context, ConvertToV8String(isolate, "entryPoint")).ToLocal(
1763
+ &entryPoint);
1764
+
1765
+
1766
+ if (!entryPoint.IsEmpty() && entryPoint->IsString()) {
1767
+ auto ep = v8::String::Utf8Value(isolate, entryPoint);
1768
+ char *entry_point = (char *) malloc(ep.length());
1769
+ std::strcpy(entry_point, *ep);
1770
+
1771
+ fragment->entry_point = entry_point;
1772
+ }
1773
+
1774
+
1775
+ v8::Local<v8::Value> moduleVal;
1776
+ fragmentValueObj->Get(context, ConvertToV8String(isolate, "module")).ToLocal(&moduleVal);
1777
+
1778
+ auto module = GPUShaderModuleImpl::GetPointer(moduleVal.As<v8::Object>());
1779
+
1780
+ fragment->module = module->GetShaderModule();
1781
+
1782
+ descriptor.fragment = fragment;
1783
+
1784
+ }
1785
+
1786
+
1787
+ v8::Local<v8::Value> labelVal;
1788
+ options->Get(context, ConvertToV8String(isolate, "label")).ToLocal(
1789
+ &labelVal);
1790
+
1791
+
1792
+ if (!labelVal.IsEmpty() && labelVal->IsString()) {
1793
+ descriptor.label = *v8::String::Utf8Value(isolate, labelVal);
1794
+ }
1795
+
1796
+
1797
+ v8::Local<v8::Value> layoutVal;
1798
+ options->Get(context, ConvertToV8String(isolate, "layout")).ToLocal(
1799
+ &layoutVal);
1800
+
1801
+ CanvasGPUPipelineLayoutOrGPUAutoLayoutMode layout;
1802
+
1803
+ if (layoutVal->IsString()) {
1804
+ layout = CanvasGPUPipelineLayoutOrGPUAutoLayoutMode{
1805
+ CanvasGPUPipelineLayoutOrGPUAutoLayoutModeAuto
1806
+ };
1807
+ } else if (!layoutVal->IsNullOrUndefined() && layoutVal->IsObject()) {
1808
+ auto pipeline = GPUPipelineLayoutImpl::GetPointer(layoutVal.As<v8::Object>());
1809
+ layout = CanvasGPUPipelineLayoutOrGPUAutoLayoutMode{
1810
+ CanvasGPUPipelineLayoutOrGPUAutoLayoutModeLayout,
1811
+ layout.layout = pipeline->GetPipeline()
1812
+ };
1813
+ } else {
1814
+ // todo throw ?
1815
+ layout = CanvasGPUPipelineLayoutOrGPUAutoLayoutMode{
1816
+ CanvasGPUPipelineLayoutOrGPUAutoLayoutModeAuto
1817
+ };
1818
+ }
1819
+
1820
+ descriptor.layout = layout;
1821
+
1822
+
1823
+ v8::Local<v8::Value> multisampleValue;
1824
+ options->Get(context, ConvertToV8String(isolate, "multisample")).ToLocal(
1825
+ &multisampleValue);
1826
+
1827
+
1828
+ CanvasMultisampleState *multisample = nullptr;
1829
+
1830
+ if (!multisampleValue.IsEmpty() && multisampleValue->IsObject()) {
1831
+ auto multisampleObj = multisampleValue.As<v8::Object>();
1832
+ multisample = new CanvasMultisampleState{};
1833
+ multisample->alpha_to_coverage_enabled = true;
1834
+ multisample->count = 1;
1835
+ multisample->mask = 0xFFFFFFFF;
1836
+
1837
+ v8::Local<v8::Value> alphaToCoverageEnabled;
1838
+ v8::Local<v8::Value> count;
1839
+ v8::Local<v8::Value> mask;
1840
+
1841
+ multisampleObj->Get(context, ConvertToV8String(isolate, "alphaToCoverageEnabled")).
1842
+ ToLocal(&alphaToCoverageEnabled);
1843
+
1844
+ if (!alphaToCoverageEnabled.IsEmpty() && alphaToCoverageEnabled->IsBoolean()) {
1845
+ multisample->alpha_to_coverage_enabled = alphaToCoverageEnabled->BooleanValue(
1846
+ isolate);
1847
+ }
1848
+
1849
+ multisampleObj->Get(context, ConvertToV8String(isolate, "count")).
1850
+ ToLocal(&count);
1851
+
1852
+ if (!count.IsEmpty() && count->IsUint32()) {
1853
+ multisample->count = count.As<v8::Uint32>()->Value();
1854
+ }
1855
+
1856
+ multisampleObj->Get(context, ConvertToV8String(isolate, "mask")).
1857
+ ToLocal(&mask);
1858
+
1859
+ if (!mask.IsEmpty() && mask->IsNumber()) {
1860
+ // todo verify mask
1861
+ auto maskValue = mask.As<v8::Number>()->Value();
1862
+ multisample->mask = (uint64_t) maskValue;
1863
+ }
1864
+
1865
+
1866
+ descriptor.multisample = multisample;
1867
+
1868
+ }
1869
+
1870
+
1871
+ v8::Local<v8::Value> primitiveValue;
1872
+ options->Get(context, ConvertToV8String(isolate, "primitive")).ToLocal(
1873
+ &primitiveValue);
1874
+
1875
+
1876
+ CanvasPrimitiveState *primitive = nullptr;
1877
+
1878
+ if (!primitiveValue.IsEmpty() && primitiveValue->IsObject()) {
1879
+ auto primitiveObj = primitiveValue.As<v8::Object>();
1880
+ primitive = new CanvasPrimitiveState{};
1881
+
1882
+ primitive->cull_mode = CanvasCullMode::CanvasCullModeNone;
1883
+ primitive->front_face = CanvasFrontFaceCcw;
1884
+ primitive->strip_index_format = CanvasOptionalIndexFormat{
1885
+ CanvasOptionalIndexFormatNone
1886
+ };
1887
+
1888
+ primitive->topology = CanvasPrimitiveTopologyTriangleList;
1889
+
1890
+ primitive->unclipped_depth = false;
1891
+
1892
+
1893
+ v8::Local<v8::Value> cullModeValue;
1894
+
1895
+ if (primitiveObj->Get(context, ConvertToV8String(isolate, "cullMode")).ToLocal(
1896
+ &cullModeValue)) {
1897
+ if (cullModeValue->IsUint32()) {
1898
+ auto cullMode = cullModeValue.As<v8::Uint32>()->Value();
1899
+
1900
+ switch (cullMode) {
1901
+ case 0:
1902
+ primitive->cull_mode = CanvasCullMode::CanvasCullModeNone;
1903
+ break;
1904
+ case 1:
1905
+ primitive->cull_mode = CanvasCullMode::CanvasCullModeFront;
1906
+ break;
1907
+ case 2:
1908
+ primitive->cull_mode = CanvasCullMode::CanvasCullModeBack;
1909
+ break;
1910
+ }
1911
+ } else if (cullModeValue->IsString()) {
1912
+
1913
+ auto cullMode = ConvertFromV8String(isolate, cullModeValue);
1914
+
1915
+ if (cullMode == "none") {
1916
+ primitive->cull_mode = CanvasCullMode::CanvasCullModeNone;
1917
+ } else if (cullMode == "front") {
1918
+ primitive->cull_mode = CanvasCullMode::CanvasCullModeFront;
1919
+ } else if (cullMode == "back") {
1920
+ primitive->cull_mode = CanvasCullMode::CanvasCullModeBack;
1921
+ }
1922
+ }
1923
+
1924
+ }
1925
+
1926
+ v8::Local<v8::Value> frontFaceValue;
1927
+
1928
+ if (primitiveObj->Get(context, ConvertToV8String(isolate, "frontFace")).ToLocal(
1929
+ &frontFaceValue)) {
1930
+ if (frontFaceValue->IsUint32()) {
1931
+ auto frontFace = frontFaceValue.As<v8::Uint32>()->Value();
1932
+ switch (frontFace) {
1933
+ case 0:
1934
+ primitive->front_face = CanvasFrontFace::CanvasFrontFaceCcw;
1935
+ break;
1936
+ case 1:
1937
+ primitive->front_face = CanvasFrontFace::CanvasFrontFaceCw;
1938
+ break;
1939
+ default:
1940
+ break;
1941
+ }
1942
+ } else if (frontFaceValue->IsString()) {
1943
+ auto frontFace = ConvertFromV8String(isolate, frontFaceValue);
1944
+ if (frontFace == "ccw") {
1945
+ primitive->front_face = CanvasFrontFace::CanvasFrontFaceCcw;
1946
+ } else if (frontFace == "cw") {
1947
+ primitive->front_face = CanvasFrontFace::CanvasFrontFaceCw;
1948
+ }
1949
+ }
1950
+ }
1951
+
1952
+
1953
+ v8::Local<v8::Value> stripIndexFormatValue;
1954
+
1955
+ if (primitiveObj->Get(context, ConvertToV8String(isolate, "stripIndexFormat")).ToLocal(
1956
+ &stripIndexFormatValue)) {
1957
+ if (stripIndexFormatValue->IsUint32()) {
1958
+ auto stripIndexFormat = stripIndexFormatValue.As<v8::Uint32>()->Value();
1959
+ switch (stripIndexFormat) {
1960
+ case 0:
1961
+ primitive->strip_index_format = CanvasOptionalIndexFormat{
1962
+ CanvasOptionalIndexFormatSome,
1963
+ CanvasIndexFormat::CanvasIndexFormatUint16
1964
+ };
1965
+ break;
1966
+ case 1:
1967
+ primitive->strip_index_format = CanvasOptionalIndexFormat{
1968
+ CanvasOptionalIndexFormatSome,
1969
+ CanvasIndexFormat::CanvasIndexFormatUint32
1970
+ };
1971
+ break;
1972
+ default:
1973
+ break;
1974
+ }
1975
+ } else if (stripIndexFormatValue->IsString()) {
1976
+ auto stripIndexFormat = ConvertFromV8String(isolate, stripIndexFormatValue);
1977
+
1978
+
1979
+ if (stripIndexFormat == "uint16") {
1980
+ primitive->strip_index_format = CanvasOptionalIndexFormat{
1981
+ CanvasOptionalIndexFormatSome,
1982
+ CanvasIndexFormat::CanvasIndexFormatUint16
1983
+ };
1984
+ } else if (stripIndexFormat == "uint32") {
1985
+ primitive->strip_index_format = CanvasOptionalIndexFormat{
1986
+ CanvasOptionalIndexFormatSome,
1987
+ CanvasIndexFormat::CanvasIndexFormatUint32
1988
+ };
1989
+ }
1990
+ }
1991
+ }
1992
+
1993
+
1994
+ v8::Local<v8::Value> topologyValue;
1995
+
1996
+ if (primitiveObj->Get(context, ConvertToV8String(isolate, "topology")).ToLocal(
1997
+ &topologyValue)) {
1998
+
1999
+ if (topologyValue->IsUint32()) {
2000
+ auto topology = topologyValue.As<v8::Uint32>()->Value();
2001
+ switch (topology) {
2002
+ case 0:
2003
+ primitive->topology = CanvasPrimitiveTopology::CanvasPrimitiveTopologyPointList;
2004
+ break;
2005
+ case 1:
2006
+ primitive->topology = CanvasPrimitiveTopology::CanvasPrimitiveTopologyLineList;
2007
+ break;
2008
+ case 2:
2009
+ primitive->topology = CanvasPrimitiveTopology::CanvasPrimitiveTopologyLineStrip;
2010
+ break;
2011
+ case 3:
2012
+ primitive->topology = CanvasPrimitiveTopology::CanvasPrimitiveTopologyTriangleList;
2013
+ break;
2014
+ case 4:
2015
+ primitive->topology = CanvasPrimitiveTopology::CanvasPrimitiveTopologyTriangleStrip;
2016
+ break;
2017
+ default:
2018
+ break;
2019
+ }
2020
+ } else if (topologyValue->IsString()) {
2021
+ auto topology = ConvertFromV8String(isolate, topologyValue);
2022
+ if (topology == "line-list") {
2023
+ primitive->topology = CanvasPrimitiveTopology::CanvasPrimitiveTopologyLineList;
2024
+ } else if (topology == "line-strip") {
2025
+ primitive->topology = CanvasPrimitiveTopology::CanvasPrimitiveTopologyLineStrip;
2026
+ } else if (topology == "point-list") {
2027
+ primitive->topology = CanvasPrimitiveTopology::CanvasPrimitiveTopologyPointList;
2028
+ } else if (topology == "triangle-list") {
2029
+ primitive->topology = CanvasPrimitiveTopology::CanvasPrimitiveTopologyTriangleList;
2030
+ } else if (topology == "triangle-strip") {
2031
+ primitive->topology = CanvasPrimitiveTopology::CanvasPrimitiveTopologyTriangleStrip;
2032
+ }
2033
+ }
2034
+
2035
+ }
2036
+
2037
+
2038
+ v8::Local<v8::Value> unclippedDepthValue;
2039
+ primitiveObj->Get(context, ConvertToV8String(isolate, "unclippedDepth")).ToLocal(
2040
+ &unclippedDepthValue);
2041
+
2042
+ if (!unclippedDepthValue.IsEmpty() && unclippedDepthValue->IsBoolean()) {
2043
+ primitive->unclipped_depth = unclippedDepthValue->BooleanValue(isolate);
2044
+ }
2045
+
2046
+ descriptor.primitive = primitive;
2047
+
2048
+ }
2049
+
2050
+
2051
+ v8::Local<v8::Value> vertexValue;
2052
+ options->Get(context, ConvertToV8String(isolate, "vertex")).ToLocal(
2053
+ &vertexValue);
2054
+
2055
+
2056
+ CanvasVertexState *vertex = nullptr;
2057
+
2058
+ std::vector<CanvasVertexBufferLayout> bufferLayout;
2059
+
2060
+ std::vector<std::vector<CanvasVertexAttribute>> attributes;
2061
+
2062
+
2063
+ if (!vertexValue.IsEmpty() && vertexValue->IsObject()) {
2064
+ auto vertexObj = vertexValue.As<v8::Object>();
2065
+ vertex = new CanvasVertexState{};
2066
+
2067
+ v8::Local<v8::Value> moduleVal;
2068
+ vertexObj->Get(context, ConvertToV8String(isolate, "module")).ToLocal(&moduleVal);
2069
+
2070
+ auto module = GPUShaderModuleImpl::GetPointer(moduleVal.As<v8::Object>());
2071
+
2072
+ vertex->module = module->GetShaderModule();
2073
+
2074
+ v8::Local<v8::Value> constantsVal;
2075
+ vertexObj->Get(context, ConvertToV8String(isolate, "constants")).ToLocal(&constantsVal);
2076
+
2077
+ if (!constantsVal.IsEmpty() && constantsVal->IsMap()) {
2078
+ auto constants = constantsVal.As<v8::Map>();
2079
+ auto keyValues = constants->AsArray();
2080
+ auto len = keyValues->Length();
2081
+ CanvasConstants *store = nullptr;
2082
+
2083
+ if (len > 0) {
2084
+ store = canvas_native_webgpu_constants_create();
2085
+ for (int i = 0; i < len; i += 2) {
2086
+ auto k = i;
2087
+ auto v = k + 1;
2088
+
2089
+ v8::Local<v8::Value> keyVal;
2090
+ keyValues->Get(context, k).ToLocal(&keyVal);
2091
+ v8::Local<v8::Value> valueVal;
2092
+ keyValues->Get(context, v).ToLocal(&valueVal);
2093
+
2094
+
2095
+ if (!keyVal.IsEmpty() && keyVal->IsString() && !valueVal.IsEmpty() &&
2096
+ valueVal->IsNumber()) {
2097
+ canvas_native_webgpu_constants_insert(
2098
+ store,
2099
+ *v8::String::Utf8Value(isolate, keyVal),
2100
+ valueVal.As<v8::Number>()->Value()
2101
+ );
2102
+ }
2103
+
2104
+ }
2105
+ }
2106
+
2107
+ vertex->constants = store;
2108
+
2109
+ }
2110
+
2111
+ v8::Local<v8::Value> buffersVal;
2112
+ vertexObj->Get(context, ConvertToV8String(isolate, "buffers")).ToLocal(&buffersVal);
2113
+
2114
+ uint64_t stride = 0;
2115
+ if (!buffersVal.IsEmpty() && buffersVal->IsArray()) {
2116
+ auto buffers = buffersVal.As<v8::Array>();
2117
+ auto len = buffers->Length();
2118
+
2119
+ for (int i = 0; i < len; i++) {
2120
+ auto buffer = buffers->Get(context, i).ToLocalChecked().As<v8::Object>();
2121
+
2122
+ v8::Local<v8::Value> arrayStride;
2123
+
2124
+ buffer->Get(context, ConvertToV8String(isolate, "arrayStride")).ToLocal(
2125
+ &arrayStride);
2126
+
2127
+ if (!arrayStride.IsEmpty() && arrayStride->IsNumber()) {
2128
+ stride = (uint64_t) arrayStride.As<v8::Number>()->Value();
2129
+ }
2130
+
2131
+ std::vector<CanvasVertexAttribute> attributes_;
2132
+
2133
+ v8::Local<v8::Value> attributesValue;
2134
+
2135
+ buffer->Get(context, ConvertToV8String(isolate, "attributes")).ToLocal(
2136
+ &attributesValue);
2137
+
2138
+ if (!attributesValue.IsEmpty() && attributesValue->IsArray()) {
2139
+ auto attributes_array = attributesValue.As<v8::Array>();
2140
+ auto attributes_len = attributes_array->Length();
2141
+
2142
+ for (int j = 0; j < attributes_len; j++) {
2143
+ auto attr = attributes_array->Get(context,
2144
+ j).ToLocalChecked().As<v8::Object>();
2145
+ auto format = attr->Get(context, ConvertToV8String(isolate,
2146
+ "format")).ToLocalChecked()->Uint32Value(
2147
+ context).ToChecked();
2148
+
2149
+ auto offset = (uint64_t) attr->Get(context, ConvertToV8String(isolate,
2150
+ "offset")).ToLocalChecked()->NumberValue(
2151
+ context).ToChecked();
2152
+ auto shaderLocation = attr->Get(context, ConvertToV8String(isolate,
2153
+ "shaderLocation")).ToLocalChecked()->Uint32Value(
2154
+ context).ToChecked();
2155
+
2156
+ auto attribute = CanvasVertexAttribute{
2157
+ (CanvasVertexFormat) format,
2158
+ offset,
2159
+ shaderLocation
2160
+ };
2161
+
2162
+ attributes_.push_back(attribute);
2163
+ }
2164
+
2165
+ attributes.push_back(attributes_);
2166
+ }
2167
+
2168
+
2169
+ CanvasVertexStepMode stepMode = CanvasVertexStepModeVertex;
2170
+
2171
+ v8::Local<v8::Value> stepModeVal;
2172
+
2173
+ buffer->Get(context, ConvertToV8String(isolate, "stepMode")).ToLocal(
2174
+ &stepModeVal);
2175
+
2176
+
2177
+ if (!stepModeVal.IsEmpty()) {
2178
+ if (stepModeVal->IsUint32()) {
2179
+ switch (stepModeVal.As<v8::Uint32>()->Value()) {
2180
+ case 0:
2181
+ stepMode = CanvasVertexStepMode::CanvasVertexStepModeVertex;
2182
+ break;
2183
+ case 1:
2184
+ stepMode = CanvasVertexStepMode::CanvasVertexStepModeInstance;
2185
+ break;
2186
+ }
2187
+ } else if (stepModeVal->IsString()) {
2188
+ auto stepModeStr = ConvertFromV8String(isolate, stepModeVal);
2189
+ if (stepModeStr == "vertex") {
2190
+ stepMode = CanvasVertexStepMode::CanvasVertexStepModeVertex;
2191
+ } else if (stepModeStr == "instance") {
2192
+ stepMode = CanvasVertexStepMode::CanvasVertexStepModeInstance;
2193
+ }
2194
+ }
2195
+ }
2196
+
2197
+ auto vertexBufferLayout = CanvasVertexBufferLayout{
2198
+ stride,
2199
+ stepMode,
2200
+ attributes[i].data(),
2201
+ attributes[i].size()
2202
+ };
2203
+
2204
+ bufferLayout.push_back(vertexBufferLayout);
2205
+ }
2206
+
2207
+ vertex->buffers = bufferLayout.data();
2208
+ vertex->buffers_size = bufferLayout.size();
2209
+
2210
+ }
2211
+
2212
+
2213
+ v8::Local<v8::Value> entryPoint;
2214
+ vertexObj->Get(context, ConvertToV8String(isolate, "entryPoint")).ToLocal(&entryPoint);
2215
+
2216
+
2217
+ if (!entryPoint.IsEmpty() && entryPoint->IsString()) {
2218
+ auto ep = v8::String::Utf8Value(isolate, entryPoint);
2219
+ char *entry_point = (char *) malloc(ep.length());
2220
+ std::strcpy(entry_point, *ep);
2221
+ vertex->entry_point = entry_point;
2222
+ }
2223
+
2224
+ descriptor.vertex = vertex;
2225
+
2226
+ }
2227
+
2228
+
2229
+ auto pipeline = canvas_native_webgpu_device_create_render_pipeline(ptr->GetGPUDevice(),
2230
+ &descriptor);
2231
+
2232
+
2233
+ if (descriptor.fragment != nullptr) {
2234
+ if (descriptor.fragment->entry_point != nullptr) {
2235
+ free((void *) descriptor.fragment->entry_point);
2236
+ }
2237
+ }
2238
+
2239
+ if (descriptor.primitive != nullptr) {
2240
+ delete descriptor.primitive;
2241
+ }
2242
+
2243
+ if (descriptor.multisample != nullptr) {
2244
+ delete descriptor.multisample;
2245
+ }
2246
+
2247
+
2248
+ if (descriptor.vertex != nullptr) {
2249
+ if (descriptor.vertex->constants != nullptr) {
2250
+ canvas_native_webgpu_constants_destroy(
2251
+ (CanvasConstants *) descriptor.vertex->constants);
2252
+ }
2253
+
2254
+ if (descriptor.vertex->entry_point != nullptr) {
2255
+ free((void *) descriptor.vertex->entry_point);
2256
+ }
2257
+
2258
+ }
2259
+
2260
+
2261
+ if (pipeline != nullptr) {
2262
+ auto ret = GPURenderPipelineImpl::NewInstance(isolate, new GPURenderPipelineImpl(pipeline));
2263
+ args.GetReturnValue().Set(ret);
2264
+ return;
2265
+ }
2266
+
2267
+ args.GetReturnValue().SetUndefined();
2268
+ }
2269
+
2270
+ void GPUDeviceImpl::CreateSampler(const v8::FunctionCallbackInfo<v8::Value> &args) {
2271
+ GPUDeviceImpl *ptr = GetPointer(args.This());
2272
+ if (ptr == nullptr) {
2273
+ return;
2274
+ }
2275
+ auto isolate = args.GetIsolate();
2276
+ auto context = isolate->GetCurrentContext();
2277
+
2278
+
2279
+ auto optionsVal = args[0];
2280
+
2281
+ if (!optionsVal->IsNullOrUndefined() && optionsVal->IsObject()) {
2282
+ auto options = optionsVal.As<v8::Object>();
2283
+
2284
+ v8::Local<v8::Value> labelVal;
2285
+ options->Get(context, ConvertToV8String(isolate, "label")).ToLocal(&labelVal);
2286
+
2287
+ char *label = nullptr;
2288
+
2289
+ if (!labelVal.IsEmpty() && labelVal->IsString()) {
2290
+ label = *v8::String::Utf8Value(isolate, labelVal);
2291
+ }
2292
+
2293
+ auto addressModeU = CanvasAddressModeClampToEdge;
2294
+
2295
+ v8::Local<v8::Value> addressModeUVal;
2296
+ options->Get(context, ConvertToV8String(isolate, "addressModeU")).ToLocal(&addressModeUVal);
2297
+ auto addressModeUStr = ConvertFromV8String(isolate, addressModeUVal);
2298
+ if (addressModeUStr == "repeat") {
2299
+ addressModeU = CanvasAddressModeRepeat;
2300
+ } else if (addressModeUStr == "mirror-repeat") {
2301
+ addressModeU = CanvasAddressModeMirrorRepeat;
2302
+ }
2303
+
2304
+
2305
+ auto addressModeV = CanvasAddressModeClampToEdge;
2306
+
2307
+ v8::Local<v8::Value> addressModeVVal;
2308
+ options->Get(context, ConvertToV8String(isolate, "addressModeV")).ToLocal(&addressModeVVal);
2309
+ auto addressModeVStr = ConvertFromV8String(isolate, addressModeVVal);
2310
+ if (addressModeVStr == "repeat") {
2311
+ addressModeV = CanvasAddressModeRepeat;
2312
+ } else if (addressModeVStr == "mirror-repeat") {
2313
+ addressModeV = CanvasAddressModeMirrorRepeat;
2314
+ }
2315
+
2316
+
2317
+ auto addressModeW = CanvasAddressModeClampToEdge;
2318
+
2319
+ v8::Local<v8::Value> addressModeWVal;
2320
+ options->Get(context, ConvertToV8String(isolate, "addressModeW")).ToLocal(&addressModeWVal);
2321
+ auto addressModeWStr = ConvertFromV8String(isolate, addressModeWVal);
2322
+ if (addressModeWStr == "repeat") {
2323
+ addressModeW = CanvasAddressModeRepeat;
2324
+ } else if (addressModeWStr == "mirror-repeat") {
2325
+ addressModeW = CanvasAddressModeMirrorRepeat;
2326
+ }
2327
+
2328
+
2329
+ auto magFilter = CanvasFilterModeNearest;
2330
+
2331
+ v8::Local<v8::Value> magFilterVal;
2332
+ options->Get(context, ConvertToV8String(isolate, "magFilter")).ToLocal(&magFilterVal);
2333
+ auto magFilterStr = ConvertFromV8String(isolate, magFilterVal);
2334
+ if (magFilterStr == "linear") {
2335
+ magFilter = CanvasFilterModeLinear;
2336
+ }
2337
+
2338
+ auto minFilter = CanvasFilterModeNearest;
2339
+
2340
+ v8::Local<v8::Value> minFilterVal;
2341
+ options->Get(context, ConvertToV8String(isolate, "minFilter")).ToLocal(&minFilterVal);
2342
+ auto minFilterStr = ConvertFromV8String(isolate, minFilterVal);
2343
+ if (minFilterStr == "linear") {
2344
+ minFilter = CanvasFilterModeLinear;
2345
+ }
2346
+
2347
+
2348
+ auto mipmapFilter = CanvasFilterModeNearest;
2349
+
2350
+ v8::Local<v8::Value> mipmapFilterVal;
2351
+ options->Get(context, ConvertToV8String(isolate, "mipmapFilter")).ToLocal(&mipmapFilterVal);
2352
+ auto mipmapFilterStr = ConvertFromV8String(isolate, mipmapFilterVal);
2353
+ if (mipmapFilterStr == "linear") {
2354
+ mipmapFilter = CanvasFilterModeLinear;
2355
+ }
2356
+
2357
+
2358
+ float lodMinClamp = 0;
2359
+
2360
+ v8::Local<v8::Value> lodMinClampVal;
2361
+ options->Get(context, ConvertToV8String(isolate, "lodMinClamp")).ToLocal(&lodMinClampVal);
2362
+
2363
+ if (!lodMinClampVal.IsEmpty() && lodMinClampVal->IsNumber()) {
2364
+ lodMinClamp = (float) lodMinClampVal->NumberValue(context).FromJust();
2365
+ }
2366
+
2367
+
2368
+ float lodMaxClamp = 32;
2369
+
2370
+ v8::Local<v8::Value> lodMaxClampVal;
2371
+ options->Get(context, ConvertToV8String(isolate, "lodMaxClamp")).ToLocal(&lodMaxClampVal);
2372
+
2373
+ if (!lodMaxClampVal.IsEmpty() && lodMaxClampVal->IsNumber()) {
2374
+ lodMaxClamp = (float) lodMaxClampVal->NumberValue(context).FromJust();
2375
+ }
2376
+
2377
+
2378
+ CanvasOptionalCompareFunction compare{
2379
+ CanvasOptionalCompareFunctionNone
2380
+ };
2381
+
2382
+
2383
+ v8::Local<v8::Value> compareVal;
2384
+ options->Get(context, ConvertToV8String(isolate, "compare")).ToLocal(&compareVal);
2385
+
2386
+ auto compareStr = ConvertFromV8String(isolate, compareVal);
2387
+
2388
+ if (compareStr == "never") {
2389
+ compare.tag = CanvasOptionalCompareFunctionSome;
2390
+ compare.some = CanvasCompareFunctionNever;
2391
+ } else if (compareStr == "less") {
2392
+ compare.tag = CanvasOptionalCompareFunctionSome;
2393
+ compare.some = CanvasCompareFunctionLess;
2394
+ } else if (compareStr == "equal") {
2395
+ compare.tag = CanvasOptionalCompareFunctionSome;
2396
+ compare.some = CanvasCompareFunctionEqual;
2397
+ } else if (compareStr == "less-equal") {
2398
+ compare.tag = CanvasOptionalCompareFunctionSome;
2399
+ compare.some = CanvasCompareFunctionLessEqual;
2400
+ } else if (compareStr == "greater") {
2401
+ compare.tag = CanvasOptionalCompareFunctionSome;
2402
+ compare.some = CanvasCompareFunctionGreater;
2403
+ } else if (compareStr == "not-equal") {
2404
+ compare.tag = CanvasOptionalCompareFunctionSome;
2405
+ compare.some = CanvasCompareFunctionNotEqual;
2406
+ } else if (compareStr == "greater-equal") {
2407
+ compare.tag = CanvasOptionalCompareFunctionSome;
2408
+ compare.some = CanvasCompareFunctionGreaterEqual;
2409
+ } else if (compareStr == "always") {
2410
+ compare.tag = CanvasOptionalCompareFunctionSome;
2411
+ compare.some = CanvasCompareFunctionAlways;
2412
+ }
2413
+
2414
+ uint16_t maxAnisotropy = 1;
2415
+
2416
+ v8::Local<v8::Value> maxAnisotropyVal;
2417
+ options->Get(context, ConvertToV8String(isolate, "maxAnisotropy")).ToLocal(
2418
+ &maxAnisotropyVal);
2419
+
2420
+ if (!maxAnisotropyVal.IsEmpty() && maxAnisotropyVal->IsNumber()) {
2421
+ maxAnisotropy = (u_short) maxAnisotropyVal->NumberValue(context).FromJust();
2422
+ }
2423
+
2424
+
2425
+ CanvasCreateSamplerDescriptor descriptor{
2426
+ label,
2427
+ addressModeU,
2428
+ addressModeV,
2429
+ addressModeW,
2430
+ magFilter,
2431
+ minFilter,
2432
+ mipmapFilter,
2433
+ lodMinClamp,
2434
+ lodMaxClamp,
2435
+ compare,
2436
+ maxAnisotropy
2437
+ };
2438
+
2439
+ auto sampler = canvas_native_webgpu_device_create_sampler(ptr->GetGPUDevice(), &descriptor);
2440
+ if (sampler != nullptr) {
2441
+ auto ret = GPUSamplerImpl::NewInstance(isolate, new GPUSamplerImpl(sampler));
2442
+ args.GetReturnValue().Set(ret);
2443
+ return;
2444
+ }
2445
+
2446
+ } else {
2447
+ auto sampler = canvas_native_webgpu_device_create_sampler(ptr->GetGPUDevice(), nullptr);
2448
+ if (sampler != nullptr) {
2449
+ auto ret = GPUSamplerImpl::NewInstance(isolate, new GPUSamplerImpl(sampler));
2450
+ args.GetReturnValue().Set(ret);
2451
+ return;
2452
+ }
2453
+ }
2454
+
2455
+ args.GetReturnValue().SetUndefined();
2456
+
2457
+ }
2458
+
2459
+ void GPUDeviceImpl::CreateShaderModule(const v8::FunctionCallbackInfo<v8::Value> &args) {
2460
+ GPUDeviceImpl *ptr = GetPointer(args.This());
2461
+ if (ptr == nullptr) {
2462
+ return;
2463
+ }
2464
+ auto isolate = args.GetIsolate();
2465
+ auto context = isolate->GetCurrentContext();
2466
+
2467
+ auto descVal = args[0];
2468
+
2469
+
2470
+ if (!descVal->IsNullOrUndefined() && descVal->IsObject()) {
2471
+ auto desc = descVal.As<v8::Object>();
2472
+
2473
+
2474
+ v8::Local<v8::Value> labelVal;
2475
+ desc->Get(context, ConvertToV8String(isolate, "label")).ToLocal(&labelVal);
2476
+
2477
+ char *label = nullptr;
2478
+
2479
+ if (!labelVal.IsEmpty() && labelVal->IsString()) {
2480
+ label = *v8::String::Utf8Value(isolate, labelVal);
2481
+ }
2482
+
2483
+ v8::Local<v8::Value> codeVal;
2484
+
2485
+ std::string code;
2486
+ if (desc->Get(context, ConvertToV8String(isolate, "code")).ToLocal(&codeVal) && codeVal->IsString()) {
2487
+ code = ConvertFromV8String(isolate, codeVal);
2488
+ }
2489
+
2490
+ auto module = canvas_native_webgpu_device_create_shader_module(ptr->GetGPUDevice(), label,
2491
+ code.c_str());
2492
+
2493
+ if (module != nullptr) {
2494
+ auto instance = new GPUShaderModuleImpl(module);
2495
+ auto ret = GPUShaderModuleImpl::NewInstance(isolate, instance);
2496
+ args.GetReturnValue().Set(ret);
2497
+ return;
2498
+ }
2499
+
2500
+ }
2501
+
2502
+ args.GetReturnValue().SetUndefined();
2503
+
2504
+
2505
+ }
2506
+
2507
+ void GPUDeviceImpl::CreateTexture(const v8::FunctionCallbackInfo<v8::Value> &args) {
2508
+ GPUDeviceImpl *ptr = GetPointer(args.This());
2509
+ if (ptr == nullptr) {
2510
+ return;
2511
+ }
2512
+ auto isolate = args.GetIsolate();
2513
+ auto context = isolate->GetCurrentContext();
2514
+
2515
+ CanvasCreateTextureDescriptor descriptor{};
2516
+ descriptor.dimension = CanvasTextureDimension::CanvasTextureDimensionD2;
2517
+ descriptor.depthOrArrayLayers = 1;
2518
+ descriptor.sampleCount = 1;
2519
+ descriptor.mipLevelCount = 1;
2520
+ descriptor.view_formats = nullptr;
2521
+ descriptor.view_formats_size = 0;
2522
+
2523
+
2524
+ char *error = nullptr;
2525
+
2526
+
2527
+ auto optionsVal = args[0];
2528
+
2529
+
2530
+ if (optionsVal->IsObject()) {
2531
+ auto options = optionsVal.As<v8::Object>();
2532
+ v8::Local<v8::Value> depthOrArrayLayersVal;
2533
+
2534
+ if (options->Get(context, ConvertToV8String(isolate, "depthOrArrayLayers")).ToLocal(
2535
+ &depthOrArrayLayersVal) && depthOrArrayLayersVal->IsUint32()) {
2536
+ descriptor.depthOrArrayLayers = depthOrArrayLayersVal.As<v8::Uint32>()->Value();
2537
+ }
2538
+
2539
+
2540
+ v8::Local<v8::Value> widthVal;
2541
+
2542
+ if ( options->Get(context, ConvertToV8String(isolate, "width")).ToLocal(
2543
+ &widthVal) &&widthVal->IsUint32()) {
2544
+ descriptor.width = widthVal.As<v8::Uint32>()->Value();
2545
+ }
2546
+
2547
+
2548
+ v8::Local<v8::Value> heightVal;
2549
+
2550
+ if (options->Get(context, ConvertToV8String(isolate, "height")).ToLocal(
2551
+ &heightVal) && heightVal->IsUint32()) {
2552
+ descriptor.height = heightVal.As<v8::Uint32>()->Value();
2553
+ }
2554
+
2555
+
2556
+ v8::Local<v8::Value> usageVal;
2557
+
2558
+ if (options->Get(context, ConvertToV8String(isolate, "usage")).ToLocal(
2559
+ &usageVal) && usageVal->IsUint32()) {
2560
+ descriptor.usage = usageVal.As<v8::Uint32>()->Value();
2561
+ }
2562
+
2563
+
2564
+ v8::Local<v8::Value> sampleCountVal;
2565
+ options->Get(context, ConvertToV8String(isolate, "sampleCount")).ToLocal(
2566
+ &sampleCountVal);
2567
+
2568
+ if (sampleCountVal->IsUint32()) {
2569
+ descriptor.sampleCount = sampleCountVal.As<v8::Uint32>()->Value();
2570
+ }
2571
+
2572
+
2573
+ v8::Local<v8::Value> mipLevelCountVal;
2574
+ options->Get(context, ConvertToV8String(isolate, "mipLevelCount")).ToLocal(
2575
+ &mipLevelCountVal);
2576
+
2577
+ if (mipLevelCountVal->IsUint32()) {
2578
+ descriptor.mipLevelCount = mipLevelCountVal.As<v8::Uint32>()->Value();
2579
+ }
2580
+
2581
+
2582
+ v8::Local<v8::Value> dimensionVal;
2583
+ options->Get(context, ConvertToV8String(isolate, "dimension")).ToLocal(
2584
+ &dimensionVal);
2585
+
2586
+ if (dimensionVal->IsString()) {
2587
+ auto dimension = ConvertFromV8String(isolate, dimensionVal);
2588
+
2589
+ // todo use enum
2590
+ if (dimension == "1d") {
2591
+ descriptor.dimension = CanvasTextureDimension::CanvasTextureDimensionD1;
2592
+ } else if (dimension == "2d") {
2593
+ descriptor.dimension = CanvasTextureDimension::CanvasTextureDimensionD2;
2594
+ } else if (dimension == "3d") {
2595
+ descriptor.dimension = CanvasTextureDimension::CanvasTextureDimensionD3;
2596
+ }
2597
+
2598
+ }
2599
+
2600
+
2601
+ v8::Local<v8::Value> formatVal;
2602
+ options->Get(context, ConvertToV8String(isolate, "format")).ToLocal(
2603
+ &formatVal);
2604
+
2605
+ if (formatVal->IsString()) {
2606
+ auto format = ConvertFromV8String(isolate, formatVal);
2607
+
2608
+ // todo use enum
2609
+ //CanvasGPUTextureFormat fmt{};
2610
+
2611
+ auto fmtOpt = canvas_native_webgpu_enum_string_to_gpu_texture(format.c_str());
2612
+ if (fmtOpt.tag == CanvasOptionalGPUTextureFormatSome) {
2613
+ descriptor.format = fmtOpt.some;
2614
+ }
2615
+ // if (strcmp(format.c_str(), "bgra8unorm") == 0) {
2616
+ // fmt.tag = CanvasGPUTextureFormat_Tag::CanvasGPUTextureFormatBgra8Unorm;
2617
+ // descriptor.format = fmt;
2618
+ // } else if (strcmp(format.c_str(), "rgba8unorm") == 0) {
2619
+ // fmt.tag = CanvasGPUTextureFormat_Tag::CanvasGPUTextureFormatRgba8Unorm;
2620
+ // descriptor.format = fmt;
2621
+ // }
2622
+
2623
+ }
2624
+
2625
+ }
2626
+
2627
+ auto texture = canvas_native_webgpu_device_create_texture(ptr->GetGPUDevice(), &descriptor);
2628
+
2629
+ if (texture != nullptr) {
2630
+ auto textureImpl = new GPUTextureImpl(texture);
2631
+ auto ret = GPUTextureImpl::NewInstance(isolate, textureImpl);
2632
+ args.GetReturnValue().Set(ret);
2633
+
2634
+ } else {
2635
+ if (error != nullptr) {
2636
+ isolate->ThrowError(ConvertToV8String(isolate, error));
2637
+ }
2638
+
2639
+ args.GetReturnValue().SetUndefined();
2640
+ }
2641
+ }
2642
+
2643
+ void GPUDeviceImpl::Destroy(const v8::FunctionCallbackInfo<v8::Value> &args) {
2644
+ GPUDeviceImpl *ptr = GetPointer(args.This());
2645
+ if (ptr == nullptr) {
2646
+ return;
2647
+ }
2648
+ canvas_native_webgpu_device_destroy(ptr->GetGPUDevice());
2649
+ }
2650
+
2651
+ void GPUDeviceImpl::PopErrorScope(const v8::FunctionCallbackInfo<v8::Value> &args) {
2652
+ GPUDeviceImpl *ptr = GetPointer(args.This());
2653
+ if (ptr == nullptr) {
2654
+ return;
2655
+ }
2656
+ auto isolate = args.GetIsolate();
2657
+ auto cb = args[0];
2658
+ auto callback = new JSICallback(isolate, cb.As<v8::Function>());
2659
+
2660
+ canvas_native_webgpu_device_pop_error_scope(ptr->GetGPUDevice(), [](CanvasGPUErrorType type,
2661
+ char *msg,
2662
+ void *data) {
2663
+ auto cb = static_cast<JSICallback *>(data);
2664
+
2665
+ v8::Isolate *isolate = cb->isolate_;
2666
+ v8::Locker locker(isolate);
2667
+ v8::Isolate::Scope isolate_scope(
2668
+ isolate);
2669
+ v8::HandleScope handle_scope(
2670
+ isolate);
2671
+ v8::Local<v8::Function> callback = cb->callback_->Get(
2672
+ isolate);
2673
+ v8::Local<v8::Context> context = callback->GetCreationContextChecked();
2674
+ v8::Context::Scope context_scope(
2675
+ context);
2676
+ v8::Local<v8::Value> typ;
2677
+ v8::Local<v8::Value> message;
2678
+ switch (type) {
2679
+ case CanvasGPUErrorType::CanvasGPUErrorTypeNone:
2680
+ typ = v8::Number::New(
2681
+ isolate, 0);
2682
+ message = v8::Null(
2683
+ isolate);
2684
+ break;
2685
+ case CanvasGPUErrorType::CanvasGPUErrorTypeLost:
2686
+ typ = v8::Number::New(
2687
+ isolate, 1);
2688
+ message = v8::Null(
2689
+ isolate);
2690
+ break;
2691
+ case CanvasGPUErrorType::CanvasGPUErrorTypeOutOfMemory:
2692
+ typ = v8::Number::New(
2693
+ isolate, 2);
2694
+ message = v8::Null(
2695
+ isolate);
2696
+ break;
2697
+ case CanvasGPUErrorType::CanvasGPUErrorTypeValidation:
2698
+ typ = v8::Number::New(
2699
+ isolate, 3);
2700
+ message = ConvertToV8String(
2701
+ isolate, msg);
2702
+ break;
2703
+ case CanvasGPUErrorType::CanvasGPUErrorTypeInternal:
2704
+ typ = v8::Number::New(
2705
+ isolate, 4);
2706
+ message = v8::Null(
2707
+ isolate);
2708
+ break;
2709
+ }
2710
+ v8::Local<v8::Value> args[2] = {
2711
+ typ, message
2712
+ };
2713
+
2714
+ callback->Call(context,
2715
+ context->Global(),
2716
+ 2, args);
2717
+
2718
+ delete static_cast<JSICallback *>(data);
2719
+ }, callback);
2720
+ }
2721
+
2722
+ void GPUDeviceImpl::PushErrorScope(const v8::FunctionCallbackInfo<v8::Value> &args) {
2723
+ GPUDeviceImpl *ptr = GetPointer(args.This());
2724
+ if (ptr == nullptr) {
2725
+ return;
2726
+ }
2727
+ auto scope = ConvertFromV8String(args.GetIsolate(), args[0]);
2728
+
2729
+ if (scope == "internal") {
2730
+ canvas_native_webgpu_device_push_error_scope(ptr->GetGPUDevice(),
2731
+ CanvasGPUErrorFilterInternal);
2732
+ } else if (scope == "out-of-memory") {
2733
+ canvas_native_webgpu_device_push_error_scope(ptr->GetGPUDevice(),
2734
+ CanvasGPUErrorFilterOutOfMemory);
2735
+ } else if (scope == "validation") {
2736
+ canvas_native_webgpu_device_push_error_scope(ptr->GetGPUDevice(),
2737
+ CanvasGPUErrorFilterValidation);
2738
+ }
2739
+
2740
+
2741
+ }