@nativescript/canvas 2.0.0-webgpu.4 → 2.0.0-webgpu.40

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 (211) hide show
  1. package/Canvas/common.d.ts +5 -10
  2. package/Canvas/common.js +61 -144
  3. package/Canvas/common.js.map +1 -1
  4. package/Canvas/index.android.d.ts +6 -5
  5. package/Canvas/index.android.js +63 -42
  6. package/Canvas/index.android.js.map +1 -1
  7. package/Canvas/index.d.ts +13 -3
  8. package/Canvas/index.ios.d.ts +9 -1
  9. package/Canvas/index.ios.js +117 -66
  10. package/Canvas/index.ios.js.map +1 -1
  11. package/Canvas/utils.d.ts +3 -0
  12. package/Canvas/utils.js +85 -0
  13. package/Canvas/utils.js.map +1 -0
  14. package/Canvas2D/CanvasRenderingContext2D/index.d.ts +3 -1
  15. package/Canvas2D/CanvasRenderingContext2D/index.js +2 -4
  16. package/Canvas2D/CanvasRenderingContext2D/index.js.map +1 -1
  17. package/Dom/Group.d.ts +1 -2
  18. package/Dom/Group.js.map +1 -1
  19. package/Dom/Image.js +0 -1
  20. package/Dom/Image.js.map +1 -1
  21. package/Dom/Paint.d.ts +1 -1
  22. package/Dom/shapes/Path.d.ts +1 -1
  23. package/ImageAsset/index.d.ts +4 -2
  24. package/ImageAsset/index.js +151 -37
  25. package/ImageAsset/index.js.map +1 -1
  26. package/ImageBitmap/index.js +107 -20
  27. package/ImageBitmap/index.js.map +1 -1
  28. package/README.md +2 -4
  29. package/WebGL/WebGLRenderingContext/common.d.ts +1 -1
  30. package/WebGL/WebGLRenderingContext/index.js +76 -32
  31. package/WebGL/WebGLRenderingContext/index.js.map +1 -1
  32. package/WebGL2/WebGL2RenderingContext/index.js +5 -5
  33. package/WebGL2/WebGL2RenderingContext/index.js.map +1 -1
  34. package/WebGPU/GPU.js +4 -3
  35. package/WebGPU/GPU.js.map +1 -1
  36. package/WebGPU/GPUAdapter.d.ts +6 -3
  37. package/WebGPU/GPUAdapter.js +31 -0
  38. package/WebGPU/GPUAdapter.js.map +1 -1
  39. package/WebGPU/GPUBindGroup.d.ts +1 -0
  40. package/WebGPU/GPUBindGroup.js +3 -0
  41. package/WebGPU/GPUBindGroup.js.map +1 -1
  42. package/WebGPU/GPUBindGroupLayout.d.ts +1 -0
  43. package/WebGPU/GPUBindGroupLayout.js +3 -0
  44. package/WebGPU/GPUBindGroupLayout.js.map +1 -1
  45. package/WebGPU/GPUBuffer.js +10 -2
  46. package/WebGPU/GPUBuffer.js.map +1 -1
  47. package/WebGPU/GPUCanvasContext.d.ts +5 -3
  48. package/WebGPU/GPUCanvasContext.js +52 -10
  49. package/WebGPU/GPUCanvasContext.js.map +1 -1
  50. package/WebGPU/GPUCommandBuffer.d.ts +1 -0
  51. package/WebGPU/GPUCommandBuffer.js +3 -0
  52. package/WebGPU/GPUCommandBuffer.js.map +1 -1
  53. package/WebGPU/GPUCommandEncoder.d.ts +3 -9
  54. package/WebGPU/GPUCommandEncoder.js +94 -41
  55. package/WebGPU/GPUCommandEncoder.js.map +1 -1
  56. package/WebGPU/GPUComputePassEncoder.d.ts +1 -0
  57. package/WebGPU/GPUComputePassEncoder.js +3 -0
  58. package/WebGPU/GPUComputePassEncoder.js.map +1 -1
  59. package/WebGPU/GPUComputePipeline.d.ts +1 -0
  60. package/WebGPU/GPUComputePipeline.js +3 -0
  61. package/WebGPU/GPUComputePipeline.js.map +1 -1
  62. package/WebGPU/GPUDevice.d.ts +17 -79
  63. package/WebGPU/GPUDevice.js +75 -91
  64. package/WebGPU/GPUDevice.js.map +1 -1
  65. package/WebGPU/GPUExternalTexture.d.ts +1 -0
  66. package/WebGPU/GPUExternalTexture.js +3 -0
  67. package/WebGPU/GPUExternalTexture.js.map +1 -1
  68. package/WebGPU/GPUPipelineLayout.d.ts +1 -0
  69. package/WebGPU/GPUPipelineLayout.js +3 -0
  70. package/WebGPU/GPUPipelineLayout.js.map +1 -1
  71. package/WebGPU/GPUQuerySet.d.ts +1 -0
  72. package/WebGPU/GPUQuerySet.js +3 -0
  73. package/WebGPU/GPUQuerySet.js.map +1 -1
  74. package/WebGPU/GPUQueue.d.ts +1 -0
  75. package/WebGPU/GPUQueue.js +65 -14
  76. package/WebGPU/GPUQueue.js.map +1 -1
  77. package/WebGPU/GPURenderBundle.d.ts +1 -0
  78. package/WebGPU/GPURenderBundle.js +3 -0
  79. package/WebGPU/GPURenderBundle.js.map +1 -1
  80. package/WebGPU/GPURenderBundleEncoder.d.ts +4 -2
  81. package/WebGPU/GPURenderBundleEncoder.js +7 -3
  82. package/WebGPU/GPURenderBundleEncoder.js.map +1 -1
  83. package/WebGPU/GPURenderPassEncoder.d.ts +5 -1
  84. package/WebGPU/GPURenderPassEncoder.js +14 -2
  85. package/WebGPU/GPURenderPassEncoder.js.map +1 -1
  86. package/WebGPU/GPURenderPipeline.d.ts +1 -0
  87. package/WebGPU/GPURenderPipeline.js +3 -0
  88. package/WebGPU/GPURenderPipeline.js.map +1 -1
  89. package/WebGPU/GPUSampler.d.ts +1 -0
  90. package/WebGPU/GPUSampler.js +3 -0
  91. package/WebGPU/GPUSampler.js.map +1 -1
  92. package/WebGPU/GPUShaderModule.d.ts +1 -1
  93. package/WebGPU/GPUShaderModule.js +2 -2
  94. package/WebGPU/GPUShaderModule.js.map +1 -1
  95. package/WebGPU/GPUTexture.d.ts +1 -0
  96. package/WebGPU/GPUTexture.js +3 -0
  97. package/WebGPU/GPUTexture.js.map +1 -1
  98. package/WebGPU/GPUTextureView.d.ts +1 -0
  99. package/WebGPU/GPUTextureView.js +3 -0
  100. package/WebGPU/GPUTextureView.js.map +1 -1
  101. package/WebGPU/Interfaces.d.ts +95 -4
  102. package/WebGPU/Types.d.ts +9 -1
  103. package/WebGPU/Utils.d.ts +6 -0
  104. package/WebGPU/Utils.js +226 -0
  105. package/WebGPU/Utils.js.map +1 -1
  106. package/angular/esm2022/index.mjs +4 -4
  107. package/angular/fesm2022/nativescript-canvas-angular.mjs +4 -4
  108. package/angular/fesm2022/nativescript-canvas-angular.mjs.map +1 -1
  109. package/common.js.map +1 -1
  110. package/index.d.ts +2 -1
  111. package/index.js +3 -2
  112. package/index.js.map +1 -1
  113. package/package.json +1 -1
  114. package/platforms/android/canvas-release.aar +0 -0
  115. package/platforms/ios/CanvasNative.xcframework/ios-arm64/CanvasNative.framework/CanvasNative +0 -0
  116. package/platforms/ios/CanvasNative.xcframework/ios-arm64/CanvasNative.framework/Headers/CanvasNative-Swift.h +61 -30
  117. package/platforms/ios/CanvasNative.xcframework/ios-arm64/CanvasNative.framework/Headers/CanvasNative.h +1 -0
  118. package/platforms/ios/CanvasNative.xcframework/ios-arm64/CanvasNative.framework/Headers/NSCMTLView.h +32 -0
  119. package/platforms/ios/CanvasNative.xcframework/ios-arm64/CanvasNative.framework/Headers/canvas_ios.h +144 -176
  120. package/platforms/ios/CanvasNative.xcframework/ios-arm64/CanvasNative.framework/Headers/canvas_native.h +342 -72
  121. package/platforms/ios/CanvasNative.xcframework/ios-arm64/CanvasNative.framework/Info.plist +0 -0
  122. package/platforms/ios/CanvasNative.xcframework/ios-arm64/CanvasNative.framework/Modules/CanvasNative.swiftmodule/Project/arm64-apple-ios.swiftsourceinfo +0 -0
  123. package/platforms/ios/CanvasNative.xcframework/ios-arm64/CanvasNative.framework/Modules/CanvasNative.swiftmodule/arm64-apple-ios.abi.json +7997 -5995
  124. package/platforms/ios/CanvasNative.xcframework/ios-arm64/CanvasNative.framework/Modules/CanvasNative.swiftmodule/arm64-apple-ios.private.swiftinterface +85 -23
  125. package/platforms/ios/CanvasNative.xcframework/ios-arm64/CanvasNative.framework/Modules/CanvasNative.swiftmodule/arm64-apple-ios.swiftdoc +0 -0
  126. package/platforms/ios/CanvasNative.xcframework/ios-arm64/CanvasNative.framework/Modules/CanvasNative.swiftmodule/arm64-apple-ios.swiftinterface +85 -23
  127. package/platforms/ios/CanvasNative.xcframework/ios-arm64/CanvasNative.framework/NSCCanvas.nib +0 -0
  128. package/platforms/ios/CanvasNative.xcframework/ios-arm64/dSYMs/CanvasNative.framework.dSYM/Contents/Resources/DWARF/CanvasNative +0 -0
  129. package/platforms/ios/CanvasNative.xcframework/ios-arm64/dSYMs/CanvasNative.framework.dSYM/Contents/Resources/Relocations/aarch64/CanvasNative.yml +681 -644
  130. package/platforms/ios/CanvasNative.xcframework/ios-arm64_x86_64-simulator/CanvasNative.framework/CanvasNative +0 -0
  131. package/platforms/ios/CanvasNative.xcframework/ios-arm64_x86_64-simulator/CanvasNative.framework/Headers/CanvasNative-Swift.h +122 -60
  132. package/platforms/ios/CanvasNative.xcframework/ios-arm64_x86_64-simulator/CanvasNative.framework/Headers/CanvasNative.h +1 -0
  133. package/platforms/ios/CanvasNative.xcframework/ios-arm64_x86_64-simulator/CanvasNative.framework/Headers/NSCMTLView.h +32 -0
  134. package/platforms/ios/CanvasNative.xcframework/ios-arm64_x86_64-simulator/CanvasNative.framework/Headers/canvas_ios.h +144 -176
  135. package/platforms/ios/CanvasNative.xcframework/ios-arm64_x86_64-simulator/CanvasNative.framework/Headers/canvas_native.h +342 -72
  136. package/platforms/ios/CanvasNative.xcframework/ios-arm64_x86_64-simulator/CanvasNative.framework/Info.plist +0 -0
  137. package/platforms/ios/CanvasNative.xcframework/ios-arm64_x86_64-simulator/CanvasNative.framework/Modules/CanvasNative.swiftmodule/Project/arm64-apple-ios-simulator.swiftsourceinfo +0 -0
  138. package/platforms/ios/CanvasNative.xcframework/ios-arm64_x86_64-simulator/CanvasNative.framework/Modules/CanvasNative.swiftmodule/Project/x86_64-apple-ios-simulator.swiftsourceinfo +0 -0
  139. package/platforms/ios/CanvasNative.xcframework/ios-arm64_x86_64-simulator/CanvasNative.framework/Modules/CanvasNative.swiftmodule/arm64-apple-ios-simulator.abi.json +7997 -5995
  140. package/platforms/ios/CanvasNative.xcframework/ios-arm64_x86_64-simulator/CanvasNative.framework/Modules/CanvasNative.swiftmodule/arm64-apple-ios-simulator.private.swiftinterface +85 -23
  141. package/platforms/ios/CanvasNative.xcframework/ios-arm64_x86_64-simulator/CanvasNative.framework/Modules/CanvasNative.swiftmodule/arm64-apple-ios-simulator.swiftdoc +0 -0
  142. package/platforms/ios/CanvasNative.xcframework/ios-arm64_x86_64-simulator/CanvasNative.framework/Modules/CanvasNative.swiftmodule/arm64-apple-ios-simulator.swiftinterface +85 -23
  143. package/platforms/ios/CanvasNative.xcframework/ios-arm64_x86_64-simulator/CanvasNative.framework/Modules/CanvasNative.swiftmodule/x86_64-apple-ios-simulator.abi.json +7997 -5995
  144. package/platforms/ios/CanvasNative.xcframework/ios-arm64_x86_64-simulator/CanvasNative.framework/Modules/CanvasNative.swiftmodule/x86_64-apple-ios-simulator.private.swiftinterface +85 -23
  145. package/platforms/ios/CanvasNative.xcframework/ios-arm64_x86_64-simulator/CanvasNative.framework/Modules/CanvasNative.swiftmodule/x86_64-apple-ios-simulator.swiftdoc +0 -0
  146. package/platforms/ios/CanvasNative.xcframework/ios-arm64_x86_64-simulator/CanvasNative.framework/Modules/CanvasNative.swiftmodule/x86_64-apple-ios-simulator.swiftinterface +85 -23
  147. package/platforms/ios/CanvasNative.xcframework/ios-arm64_x86_64-simulator/CanvasNative.framework/NSCCanvas.nib +0 -0
  148. package/platforms/ios/CanvasNative.xcframework/ios-arm64_x86_64-simulator/CanvasNative.framework/_CodeSignature/CodeResources +40 -29
  149. package/platforms/ios/CanvasNative.xcframework/ios-arm64_x86_64-simulator/dSYMs/CanvasNative.framework.dSYM/Contents/Resources/DWARF/CanvasNative +0 -0
  150. package/platforms/ios/CanvasNative.xcframework/ios-arm64_x86_64-simulator/dSYMs/CanvasNative.framework.dSYM/Contents/Resources/Relocations/aarch64/CanvasNative.yml +683 -646
  151. package/platforms/ios/CanvasNative.xcframework/ios-arm64_x86_64-simulator/dSYMs/CanvasNative.framework.dSYM/Contents/Resources/Relocations/x86_64/CanvasNative.yml +736 -684
  152. package/platforms/ios/src/NSOperationQueueWrapper.h +1 -1
  153. package/platforms/ios/src/NSOperationQueueWrapper.mm +41 -9
  154. package/platforms/ios/src/cpp/AsyncCallback.h +16 -8
  155. package/platforms/ios/src/cpp/CanvasJSIModule.cpp +310 -801
  156. package/platforms/ios/src/cpp/CanvasJSIModule.h +2 -0
  157. package/platforms/ios/src/cpp/ImageAssetImpl.cpp +578 -413
  158. package/platforms/ios/src/cpp/ImageAssetImpl.h +7 -3
  159. package/platforms/ios/src/cpp/ImageBitmapImpl.cpp +60 -3
  160. package/platforms/ios/src/cpp/ImageBitmapImpl.h +10 -3
  161. package/platforms/ios/src/cpp/PromiseCallback.h +1 -2
  162. package/platforms/ios/src/cpp/canvas2d/CanvasRenderingContext2DImpl.cpp +7 -11
  163. package/platforms/ios/src/cpp/canvas2d/CanvasRenderingContext2DImpl.h +3 -3
  164. package/platforms/ios/src/cpp/canvas2d/Path2D.h +5 -5
  165. package/platforms/ios/src/cpp/webgl/WebGLRenderingContext.cpp +106 -1
  166. package/platforms/ios/src/cpp/webgl/WebGLRenderingContextBase.cpp +6 -6
  167. package/platforms/ios/src/cpp/webgpu/GPUAdapterImpl.cpp +26 -23
  168. package/platforms/ios/src/cpp/webgpu/GPUBindGroupImpl.cpp +31 -5
  169. package/platforms/ios/src/cpp/webgpu/GPUBindGroupImpl.h +4 -1
  170. package/platforms/ios/src/cpp/webgpu/GPUBindGroupLayoutImpl.cpp +26 -0
  171. package/platforms/ios/src/cpp/webgpu/GPUBindGroupLayoutImpl.h +3 -0
  172. package/platforms/ios/src/cpp/webgpu/GPUBufferImpl.cpp +41 -7
  173. package/platforms/ios/src/cpp/webgpu/GPUBufferImpl.h +4 -0
  174. package/platforms/ios/src/cpp/webgpu/GPUCanvasContextImpl.cpp +11 -5
  175. package/platforms/ios/src/cpp/webgpu/GPUCommandBufferImpl.cpp +28 -1
  176. package/platforms/ios/src/cpp/webgpu/GPUCommandBufferImpl.h +3 -0
  177. package/platforms/ios/src/cpp/webgpu/GPUCommandEncoderImpl.cpp +75 -79
  178. package/platforms/ios/src/cpp/webgpu/GPUCommandEncoderImpl.h +4 -0
  179. package/platforms/ios/src/cpp/webgpu/GPUComputePassEncoderImpl.cpp +56 -23
  180. package/platforms/ios/src/cpp/webgpu/GPUComputePassEncoderImpl.h +3 -0
  181. package/platforms/ios/src/cpp/webgpu/GPUComputePipelineImpl.cpp +25 -0
  182. package/platforms/ios/src/cpp/webgpu/GPUComputePipelineImpl.h +2 -0
  183. package/platforms/ios/src/cpp/webgpu/GPUDeviceImpl.cpp +1606 -681
  184. package/platforms/ios/src/cpp/webgpu/GPUDeviceImpl.h +2 -0
  185. package/platforms/ios/src/cpp/webgpu/GPUImpl.cpp +2 -1
  186. package/platforms/ios/src/cpp/webgpu/GPUImpl.h +1 -1
  187. package/platforms/ios/src/cpp/webgpu/GPULabel.h +33 -0
  188. package/platforms/ios/src/cpp/webgpu/GPUPipelineLayoutImpl.cpp +26 -0
  189. package/platforms/ios/src/cpp/webgpu/GPUPipelineLayoutImpl.h +3 -1
  190. package/platforms/ios/src/cpp/webgpu/GPUQuerySetImpl.cpp +1 -2
  191. package/platforms/ios/src/cpp/webgpu/GPUQuerySetImpl.h +1 -1
  192. package/platforms/ios/src/cpp/webgpu/GPUQueueImpl.cpp +83 -14
  193. package/platforms/ios/src/cpp/webgpu/GPUQueueImpl.h +3 -0
  194. package/platforms/ios/src/cpp/webgpu/GPURenderBundleEncoderImpl.cpp +66 -34
  195. package/platforms/ios/src/cpp/webgpu/GPURenderBundleEncoderImpl.h +3 -0
  196. package/platforms/ios/src/cpp/webgpu/GPURenderBundleImpl.cpp +25 -0
  197. package/platforms/ios/src/cpp/webgpu/GPURenderBundleImpl.h +3 -0
  198. package/platforms/ios/src/cpp/webgpu/GPURenderPassEncoderImpl.cpp +151 -52
  199. package/platforms/ios/src/cpp/webgpu/GPURenderPassEncoderImpl.h +7 -0
  200. package/platforms/ios/src/cpp/webgpu/GPURenderPipelineImpl.cpp +25 -0
  201. package/platforms/ios/src/cpp/webgpu/GPURenderPipelineImpl.h +3 -0
  202. package/platforms/ios/src/cpp/webgpu/GPUSamplerImpl.cpp +26 -0
  203. package/platforms/ios/src/cpp/webgpu/GPUSamplerImpl.h +4 -1
  204. package/platforms/ios/src/cpp/webgpu/GPUShaderModuleImpl.cpp +24 -0
  205. package/platforms/ios/src/cpp/webgpu/GPUShaderModuleImpl.h +3 -0
  206. package/platforms/ios/src/cpp/webgpu/GPUTextureImpl.cpp +34 -8
  207. package/platforms/ios/src/cpp/webgpu/GPUTextureImpl.h +2 -0
  208. package/platforms/ios/src/cpp/webgpu/GPUTextureViewImpl.cpp +26 -0
  209. package/platforms/ios/src/cpp/webgpu/GPUTextureViewImpl.h +3 -0
  210. package/platforms/ios/src/cpp/webgpu/GPUUtils.h +511 -0
  211. package/utils.d.ts +1 -1
@@ -21,6 +21,7 @@
21
21
  #include "GPUQuerySetImpl.h"
22
22
  #include "GPURenderBundleEncoderImpl.h"
23
23
  #include "GPUUtils.h"
24
+ #include "GPULabel.h"
24
25
 
25
26
  GPUDeviceImpl::GPUDeviceImpl(const CanvasGPUDevice *device) : device_(device) {}
26
27
 
@@ -63,6 +64,11 @@ v8::Local<v8::FunctionTemplate> GPUDeviceImpl::GetCtor(v8::Isolate *isolate) {
63
64
  auto tmpl = ctorTmpl->InstanceTemplate();
64
65
  tmpl->SetInternalFieldCount(2);
65
66
 
67
+ tmpl->SetLazyDataProperty(
68
+ ConvertToV8String(isolate, "label"),
69
+ GetLabel
70
+ );
71
+
66
72
  tmpl->SetLazyDataProperty(
67
73
  ConvertToV8String(isolate, "features"),
68
74
  GetFeatures
@@ -103,6 +109,10 @@ v8::Local<v8::FunctionTemplate> GPUDeviceImpl::GetCtor(v8::Isolate *isolate) {
103
109
  ConvertToV8String(isolate, "createComputePipeline"),
104
110
  v8::FunctionTemplate::New(isolate, &CreateComputePipeline));
105
111
 
112
+ tmpl->Set(
113
+ ConvertToV8String(isolate, "createComputePipelineAsync"),
114
+ v8::FunctionTemplate::New(isolate, &CreateComputePipelineAsync));
115
+
106
116
  tmpl->Set(
107
117
  ConvertToV8String(isolate, "createPipelineLayout"),
108
118
  v8::FunctionTemplate::New(isolate, &CreatePipelineLayout));
@@ -119,6 +129,10 @@ v8::Local<v8::FunctionTemplate> GPUDeviceImpl::GetCtor(v8::Isolate *isolate) {
119
129
  ConvertToV8String(isolate, "createRenderPipeline"),
120
130
  v8::FunctionTemplate::New(isolate, &CreateRenderPipeline));
121
131
 
132
+ tmpl->Set(
133
+ ConvertToV8String(isolate, "createRenderPipelineAsync"),
134
+ v8::FunctionTemplate::New(isolate, &CreateRenderPipelineAsync));
135
+
122
136
  tmpl->Set(
123
137
  ConvertToV8String(isolate, "createSampler"),
124
138
  v8::FunctionTemplate::New(isolate, &CreateSampler));
@@ -154,6 +168,26 @@ v8::Local<v8::FunctionTemplate> GPUDeviceImpl::GetCtor(v8::Isolate *isolate) {
154
168
  return ctorTmpl;
155
169
  }
156
170
 
171
+ void
172
+ GPUDeviceImpl::GetLabel(v8::Local<v8::Name> name,
173
+ const v8::PropertyCallbackInfo<v8::Value> &info) {
174
+ auto ptr = GetPointer(info.This());
175
+ if (ptr != nullptr) {
176
+ auto label = canvas_native_webgpu_device_get_label(ptr->device_);
177
+ if (label == nullptr) {
178
+ info.GetReturnValue().SetEmptyString();
179
+ return;
180
+ }
181
+ info.GetReturnValue().Set(
182
+ ConvertToV8String(info.GetIsolate(), label)
183
+ );
184
+ canvas_native_string_destroy(label);
185
+ return;
186
+ }
187
+
188
+ info.GetReturnValue().SetEmptyString();
189
+ }
190
+
157
191
  void
158
192
  GPUDeviceImpl::SetUncapturedError(const v8::FunctionCallbackInfo<v8::Value> &args) {
159
193
  auto *ptr = GetPointer(args.This());
@@ -244,19 +278,19 @@ GPUDeviceImpl::GetFeatures(v8::Local<v8::Name> name,
244
278
 
245
279
  auto len = canvas_native_string_buffer_get_length(features);
246
280
 
247
- auto map = v8::Map::New(isolate);
281
+ auto set = v8::Set::New(isolate);
248
282
  for (int i = 0; i < len; ++i) {
249
283
  auto item = canvas_native_string_buffer_get_value_at(features, i);
250
284
  if (item != nullptr) {
251
285
  auto keyValue = ConvertToV8String(isolate, (char *) item);
252
- map->Set(context, keyValue, keyValue);
286
+ set->Add(context, keyValue);
253
287
  canvas_native_string_destroy(item);
254
288
  }
255
289
 
256
290
  }
257
291
  canvas_native_string_buffer_release(features);
258
292
 
259
- info.GetReturnValue().Set(map);
293
+ info.GetReturnValue().Set(set);
260
294
 
261
295
  return;
262
296
  }
@@ -399,7 +433,7 @@ void GPUDeviceImpl::CreateBindGroup(const v8::FunctionCallbackInfo<v8::Value> &a
399
433
  }
400
434
  auto isolate = args.GetIsolate();
401
435
  auto context = isolate->GetCurrentContext();
402
- char *label = nullptr;
436
+ GPULabel label;
403
437
 
404
438
  auto optionsVal = args[0];
405
439
 
@@ -410,12 +444,10 @@ void GPUDeviceImpl::CreateBindGroup(const v8::FunctionCallbackInfo<v8::Value> &a
410
444
  v8::Local<v8::Value> labelVal;
411
445
  options->Get(context, ConvertToV8String(isolate, "label")).ToLocal(&labelVal);
412
446
 
413
- if (!labelVal.IsEmpty() && labelVal->IsString()) {
414
- label = *v8::String::Utf8Value(isolate, labelVal);
415
- }
416
447
 
417
- const CanvasGPUBindGroupLayout *layout = nullptr;
448
+ label = GPULabel(isolate, labelVal);
418
449
 
450
+ const CanvasGPUBindGroupLayout *layout = nullptr;
419
451
 
420
452
  v8::Local<v8::Value> layoutVal;
421
453
  options->Get(context, ConvertToV8String(isolate, "layout")).ToLocal(&layoutVal);
@@ -432,108 +464,10 @@ void GPUDeviceImpl::CreateBindGroup(const v8::FunctionCallbackInfo<v8::Value> &a
432
464
  v8::Local<v8::Value> entriesVal;
433
465
  options->Get(context, ConvertToV8String(isolate, "entries")).ToLocal(&entriesVal);
434
466
 
435
- if (!entriesVal.IsEmpty() && entriesVal->IsArray()) {
436
- auto entriesArray = entriesVal.As<v8::Array>();
437
- auto len = entriesArray->Length();
438
- for (int i = 0; i < len; i++) {
439
- v8::Local<v8::Value> entryVal;
440
- entriesArray->Get(context, i).ToLocal(&entryVal);
441
- if (!entryVal.IsEmpty() && entryVal->IsObject()) {
442
- auto entryObj = entryVal.As<v8::Object>();
443
- auto binding = entryObj->Get(context, ConvertToV8String(isolate,
444
- "binding")).ToLocalChecked()->Uint32Value(
445
- context).FromJust();
446
- v8::Local<v8::Value> resourceVal;
447
- entryObj->Get(context, ConvertToV8String(isolate, "resource")).ToLocal(
448
- &resourceVal);
449
-
450
- auto resourceType = GetNativeType(resourceVal);
451
- switch (resourceType) {
452
- case NativeType::GPUSampler: {
453
- auto sampler = GPUSamplerImpl::GetPointer(resourceVal.As<v8::Object>());
454
- if (sampler != nullptr) {
455
- auto resource = CanvasBindGroupEntryResource{
456
- CanvasBindGroupEntryResourceSampler,
457
- };
458
- resource.sampler = sampler->GetSampler();
459
- CanvasBindGroupEntry entry{binding, resource};
460
- entries.push_back(entry);
461
- }
462
-
463
- }
464
- break;
465
- case NativeType::GPUTextureView: {
466
- auto textureView = GPUTextureViewImpl::GetPointer(
467
- resourceVal.As<v8::Object>());
468
- if (textureView != nullptr) {
469
- auto resource = CanvasBindGroupEntryResource{
470
- CanvasBindGroupEntryResourceTextureView,
471
- };
472
- resource.texture_view = textureView->GetTextureView();
473
- CanvasBindGroupEntry entry{binding, resource};
474
- entries.push_back(entry);
475
- }
476
- }
477
- break;
478
- default: {
479
- if (!resourceVal.IsEmpty() && resourceVal->IsObject()) {
480
- auto resourceObj = resourceVal.As<v8::Object>();
481
- v8::Local<v8::Value> bufferVal;
482
- resourceObj->Get(context,
483
- ConvertToV8String(isolate, "buffer")).ToLocal(
484
- &bufferVal);
485
- if (GetNativeType(bufferVal) == NativeType::GPUBuffer) {
486
- auto bufferObj = bufferVal.As<v8::Object>();
487
- auto buffer = GPUBufferImpl::GetPointer(bufferObj);
488
- if (buffer != nullptr) {
489
- auto resource = CanvasBindGroupEntryResource{
490
- CanvasBindGroupEntryResourceBuffer,
491
- };
492
- int64_t offset = -1;
493
-
494
- v8::Local<v8::Value> offsetVal;
495
-
496
- resourceObj->Get(context,
497
- ConvertToV8String(isolate,
498
- "offset")).ToLocal(
499
- &offsetVal);
500
- if (!offsetVal.IsEmpty() && offsetVal->IsNumber()) {
501
- offset = (int64_t) offsetVal->NumberValue(
502
- context).ToChecked();
503
- }
504
-
505
- int64_t size = -1;
506
-
507
- v8::Local<v8::Value> sizeVal;
508
- resourceObj->Get(context,
509
- ConvertToV8String(isolate,
510
- "size")).ToLocal(
511
- &sizeVal);
512
- if (!sizeVal.IsEmpty() && sizeVal->IsNumber()) {
513
- size = (int64_t) sizeVal->NumberValue(
514
- context).ToChecked();
515
- }
516
-
517
- resource.buffer = CanvasBufferBinding{
518
- buffer->GetGPUBuffer(), offset, size
519
- };
520
-
521
- CanvasBindGroupEntry entry{binding, resource};
522
- entries.push_back(entry);
523
- }
524
- }
525
- }
526
-
527
- }
528
- break;
529
- }
530
-
531
- }
532
- }
533
- }
534
-
467
+ entries = ParseBindGroupEntries(isolate, entriesVal);
535
468
 
536
- auto bind_group = canvas_native_webgpu_device_create_bind_group(ptr->GetGPUDevice(), label,
469
+ auto bind_group = canvas_native_webgpu_device_create_bind_group(ptr->GetGPUDevice(),
470
+ *label,
537
471
  layout, entries.data(),
538
472
  entries.size());
539
473
 
@@ -554,7 +488,7 @@ void GPUDeviceImpl::CreateBindGroupLayout(const v8::FunctionCallbackInfo<v8::Val
554
488
  }
555
489
  auto isolate = args.GetIsolate();
556
490
  auto context = isolate->GetCurrentContext();
557
- char *label = nullptr;
491
+ GPULabel label;
558
492
 
559
493
  auto optionsVal = args[0];
560
494
 
@@ -563,381 +497,16 @@ void GPUDeviceImpl::CreateBindGroupLayout(const v8::FunctionCallbackInfo<v8::Val
563
497
  v8::Local<v8::Value> labelVal;
564
498
  options->Get(context, ConvertToV8String(isolate, "label")).ToLocal(&labelVal);
565
499
 
566
- if (!labelVal.IsEmpty() && labelVal->IsString()) {
567
- label = *v8::String::Utf8Value(isolate, labelVal);
568
- }
569
-
570
-
571
- std::vector<CanvasBindGroupLayoutEntry> entries;
500
+ label = GPULabel(isolate, labelVal);
572
501
 
573
502
  v8::Local<v8::Value> entriesVal;
574
503
  options->Get(context, ConvertToV8String(isolate, "entries")).ToLocal(&entriesVal);
575
504
 
576
- if (!entriesVal.IsEmpty() && entriesVal->IsArray()) {
577
- auto entriesArray = entriesVal.As<v8::Array>();
578
- auto len = entriesArray->Length();
579
- for (int i = 0; i < len; i++) {
580
- v8::Local<v8::Value> entryVal;
581
- entriesArray->Get(context, i).ToLocal(&entryVal);
582
- if (!entryVal.IsEmpty() && entryVal->IsObject()) {
583
- auto entryObj = entryVal.As<v8::Object>();
584
- auto binding = entryObj->Get(context, ConvertToV8String(isolate,
585
- "binding")).ToLocalChecked()->Uint32Value(
586
- context).FromJust();
587
- v8::Local<v8::Value> resourceVal;
588
- entryObj->Get(context, ConvertToV8String(isolate, "resource")).ToLocal(
589
- &resourceVal);
590
-
591
-
592
- auto visibility = entryObj->Get(context, ConvertToV8String(isolate,
593
- "visibility")).ToLocalChecked()->Uint32Value(
594
- context).FromJust();
595
-
596
-
597
- v8::Local<v8::Value> bufferVal;
598
-
599
- entryObj->Get(context, ConvertToV8String(isolate, "buffer")).ToLocal(
600
- &bufferVal);
601
-
602
-
603
- if (!bufferVal.IsEmpty() && bufferVal->IsObject()) {
604
- auto bufferObj = bufferVal.As<v8::Object>();
605
- v8::Local<v8::Value> bufferType;
606
- bufferObj->Get(context, ConvertToV8String(isolate, "type")).ToLocal(
607
- &bufferType);
608
-
609
- CanvasBufferBindingType type = CanvasBufferBindingTypeUniform;
610
-
611
- if (!bufferType.IsEmpty() && bufferType->IsString()) {
612
- auto typeStr = ConvertFromV8String(isolate, bufferType);
613
- if (typeStr == "read-only-storage") {
614
- type = CanvasBufferBindingTypeReadOnlyStorage;
615
- } else if (typeStr == "storage") {
616
- type = CanvasBufferBindingTypeStorage;
617
- } else if (typeStr == "uniform") {
618
- type = CanvasBufferBindingTypeUniform;
619
- }
620
- }
621
-
622
- bool has_dynamic_offset = false;
623
-
624
- v8::Local<v8::Value> hasDynamicOffsetVal;
625
- bufferObj->Get(context,
626
- ConvertToV8String(isolate, "hasDynamicOffset")).ToLocal(
627
- &hasDynamicOffsetVal);
628
-
629
-
630
- if (!hasDynamicOffsetVal.IsEmpty() && hasDynamicOffsetVal->IsBoolean()) {
631
- has_dynamic_offset = hasDynamicOffsetVal->BooleanValue(isolate);
632
- }
633
-
634
- int64_t min_binding_size = -1;
635
-
636
- v8::Local<v8::Value> minBindingSizeVal;
637
- bufferObj->Get(context,
638
- ConvertToV8String(isolate, "minBindingSize")).ToLocal(
639
- &minBindingSizeVal);
640
-
641
-
642
- if (!minBindingSizeVal.IsEmpty() && minBindingSizeVal->IsNumber()) {
643
- min_binding_size = (int64_t) minBindingSizeVal->NumberValue(
644
- context).ToChecked();
645
- }
646
-
647
- CanvasBindingType buffer{
648
- CanvasBindingTypeBuffer
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
- entries.push_back(entry);
663
-
664
- continue;
665
- }
666
-
667
-
668
- v8::Local<v8::Value> externalTextureVal;
669
-
670
- entryObj->Get(context, ConvertToV8String(isolate, "externalTexture")).ToLocal(
671
- &externalTextureVal);
672
-
673
- if (!externalTextureVal.IsEmpty() && externalTextureVal->IsObject()) {
674
- // todo
675
- // CanvasBindingType buffer{
676
- // CanvasBindingTypeTexture
677
- // };
678
- //
679
- // buffer.buffer = CanvasBufferBindingLayout{
680
- // type, has_dynamic_offset, min_binding_size
681
- // };
682
- //
683
- //
684
- // CanvasBindGroupLayoutEntry entry{
685
- // binding,
686
- // visibility,
687
- // buffer
688
- // };
689
-
690
- continue;
691
- }
692
-
693
-
694
- v8::Local<v8::Value> samplerVal;
695
-
696
- entryObj->Get(context, ConvertToV8String(isolate, "sampler")).ToLocal(
697
- &samplerVal);
698
-
699
- if (!samplerVal.IsEmpty() && samplerVal->IsObject()) {
700
- auto samplerObj = samplerVal.As<v8::Object>();
701
- v8::Local<v8::Value> samplerType;
702
- samplerObj->Get(context, ConvertToV8String(isolate, "type")).ToLocal(
703
- &samplerType);
704
-
705
- CanvasSamplerBindingType type = CanvasSamplerBindingTypeFiltering;
706
-
707
- if (!samplerType.IsEmpty() && samplerType->IsString()) {
708
- auto typeStr = ConvertFromV8String(isolate, samplerType);
709
- if (typeStr == "comparison") {
710
- type = CanvasSamplerBindingTypeComparison;
711
- } else if (typeStr == "non-filtering") {
712
- type = CanvasSamplerBindingTypeNonFiltering;
713
- } else if (typeStr == "filtering") {
714
- type = CanvasSamplerBindingTypeFiltering;
715
- }
716
- }
717
-
718
-
719
- CanvasBindingType sampler{
720
- CanvasBindingTypeSampler
721
- };
722
-
723
- sampler.sampler = CanvasSamplerBindingLayout{
724
- type
725
- };
726
-
727
-
728
- CanvasBindGroupLayoutEntry entry{
729
- binding,
730
- visibility,
731
- sampler
732
- };
733
-
734
- entries.push_back(entry);
735
-
736
- continue;
737
-
738
- }
739
-
740
-
741
- v8::Local<v8::Value> storageTextureVal;
742
-
743
- entryObj->Get(context, ConvertToV8String(isolate, "storageTexture")).ToLocal(
744
- &storageTextureVal);
745
-
746
- if (!storageTextureVal.IsEmpty() && storageTextureVal->IsObject()) {
747
- auto storageTextureObj = storageTextureVal.As<v8::Object>();
748
-
749
- CanvasBindingType storage{
750
- CanvasBindingTypeStorageTexture
751
- };
752
-
753
- CanvasStorageTextureAccess access = CanvasStorageTextureAccessWriteOnly;
754
-
755
- v8::Local<v8::Value> accessVal;
756
-
757
- storageTextureObj->Get(context,
758
- ConvertToV8String(isolate, "access")).ToLocal(
759
- &accessVal);
760
-
761
-
762
- if (!accessVal.IsEmpty() && accessVal->IsString()) {
763
- auto accessStr = ConvertFromV8String(isolate, accessVal);
764
-
765
- if (accessStr == "write-only") {
766
- access = CanvasStorageTextureAccessWriteOnly;
767
- } else if (accessStr == "read-only") {
768
- access = CanvasStorageTextureAccessReadOnly;
769
- } else if (accessStr == "read-write") {
770
- access = CanvasStorageTextureAccessReadWrite;
771
- }
772
- }
773
-
774
-
775
- CanvasTextureViewDimension view_dimension = CanvasTextureViewDimensionD2;
776
-
777
-
778
- v8::Local<v8::Value> viewDimensionVal;
779
-
780
- storageTextureObj->Get(context,
781
- ConvertToV8String(isolate, "viewDimension")).ToLocal(
782
- &viewDimensionVal);
783
-
784
-
785
- if (!viewDimensionVal.IsEmpty() && viewDimensionVal->IsString()) {
786
- auto viewDimensionStr = ConvertFromV8String(isolate, viewDimensionVal);
787
- if (viewDimensionStr == "1d") {
788
- view_dimension = CanvasTextureViewDimensionD1;
789
- } else if (viewDimensionStr == "2d") {
790
- view_dimension = CanvasTextureViewDimensionD2;
791
- } else if (viewDimensionStr == "2d-array") {
792
- view_dimension = CanvasTextureViewDimensionD2Array;
793
- } else if (viewDimensionStr == "cube") {
794
- view_dimension = CanvasTextureViewDimensionCube;
795
- } else if (viewDimensionStr == "cube-array") {
796
- view_dimension = CanvasTextureViewDimensionCubeArray;
797
- } else if (viewDimensionStr == "3d") {
798
- view_dimension = CanvasTextureViewDimensionD3;
799
- }
800
- }
801
-
802
-
803
- v8::Local<v8::Value> formatVal;
804
-
805
- storageTextureObj->Get(context,
806
- ConvertToV8String(isolate, "format")).ToLocal(
807
- &formatVal);
808
-
809
-
810
- if (!formatVal.IsEmpty() && formatVal->IsString()) {
811
- auto formatStr = ConvertFromV8String(isolate, formatVal);
812
- auto textureFormat = canvas_native_webgpu_enum_string_to_gpu_texture(
813
- formatStr.c_str());
814
- if (textureFormat.tag == CanvasOptionalGPUTextureFormatSome) {
815
- storage.storage_texture = CanvasStorageTextureBindingLayout{
816
- access,
817
- textureFormat.some,
818
- view_dimension
819
- };
820
-
821
- CanvasBindGroupLayoutEntry entry{
822
- binding,
823
- visibility,
824
- storage
825
- };
826
-
827
- entries.push_back(entry);
828
-
829
- continue;
830
-
831
- } else {
832
- // todo throw ??
833
- continue;
834
- }
835
- }
836
-
837
-
838
- }
839
-
840
-
841
- v8::Local<v8::Value> textureVal;
842
-
843
- entryObj->Get(context, ConvertToV8String(isolate, "texture")).ToLocal(
844
- &textureVal);
845
-
846
- if (!textureVal.IsEmpty() && textureVal->IsObject()) {
847
- auto textureObj = textureVal.As<v8::Object>();
848
- bool multisampled = false;
849
-
850
- v8::Local<v8::Value> multisampledVal;
851
-
852
- textureObj->Get(context,
853
- ConvertToV8String(isolate, "multisampled")).ToLocal(
854
- &multisampledVal);
855
-
856
- if (!multisampledVal.IsEmpty() && multisampledVal->IsBoolean()) {
857
- multisampled = multisampledVal->BooleanValue(isolate);
858
- }
859
-
860
-
861
- v8::Local<v8::Value> sampleTypeVal;
862
- textureObj->Get(context, ConvertToV8String(isolate, "sampleType")).ToLocal(
863
- &sampleTypeVal);
864
-
865
- CanvasTextureSampleType type = CanvasTextureSampleTypeFloat;
866
-
867
- if (!sampleTypeVal.IsEmpty() && sampleTypeVal->IsString()) {
868
- auto typeStr = ConvertFromV8String(isolate, sampleTypeVal);
869
- if (typeStr == "depth") {
870
- type = CanvasTextureSampleTypeDepth;
871
- } else if (typeStr == "float") {
872
- type = CanvasTextureSampleTypeFloat;
873
- } else if (typeStr == "sint") {
874
- type = CanvasTextureSampleTypeSint;
875
- } else if (typeStr == "uint") {
876
- type = CanvasTextureSampleTypeUint;
877
- } else if (typeStr == "unfilterable-float") {
878
- type = CanvasTextureSampleTypeUnfilterableFloat;
879
- }
880
- }
881
-
882
-
883
- CanvasTextureViewDimension view_dimension = CanvasTextureViewDimensionD2;
884
-
885
-
886
- v8::Local<v8::Value> viewDimensionVal;
887
-
888
- textureObj->Get(context,
889
- ConvertToV8String(isolate, "viewDimension")).ToLocal(
890
- &viewDimensionVal);
891
-
892
-
893
- if (!viewDimensionVal.IsEmpty() && viewDimensionVal->IsString()) {
894
- auto viewDimensionStr = ConvertFromV8String(isolate, viewDimensionVal);
895
- if (viewDimensionStr == "1d") {
896
- view_dimension = CanvasTextureViewDimensionD1;
897
- } else if (viewDimensionStr == "2d") {
898
- view_dimension = CanvasTextureViewDimensionD2;
899
- } else if (viewDimensionStr == "2d-array") {
900
- view_dimension = CanvasTextureViewDimensionD2Array;
901
- } else if (viewDimensionStr == "cube") {
902
- view_dimension = CanvasTextureViewDimensionCube;
903
- } else if (viewDimensionStr == "cube-array") {
904
- view_dimension = CanvasTextureViewDimensionCubeArray;
905
- } else if (viewDimensionStr == "3d") {
906
- view_dimension = CanvasTextureViewDimensionD3;
907
- }
908
- }
909
-
910
-
911
- CanvasBindingType texture{
912
- CanvasBindingTypeTexture
913
- };
914
-
915
- texture.texture = CanvasTextureBindingLayout{
916
- type,
917
- view_dimension,
918
- multisampled
919
- };
920
-
921
-
922
- CanvasBindGroupLayoutEntry entry{
923
- binding,
924
- visibility,
925
- texture
926
- };
927
-
928
- entries.push_back(entry);
929
-
930
- continue;
931
-
932
- }
933
-
934
- }
935
- }
936
- }
937
-
505
+ std::vector<CanvasBindGroupLayoutEntry> entries = ParseBindGroupLayoutEntries(isolate,
506
+ entriesVal);
938
507
 
939
508
  auto bind_group = canvas_native_webgpu_device_create_bind_group_layout(ptr->GetGPUDevice(),
940
- label,
509
+ *label,
941
510
  entries.data(),
942
511
  entries.size());
943
512
 
@@ -959,7 +528,7 @@ void GPUDeviceImpl::CreateBuffer(const v8::FunctionCallbackInfo<v8::Value> &args
959
528
  }
960
529
  auto isolate = args.GetIsolate();
961
530
  auto context = isolate->GetCurrentContext();
962
- char *label = nullptr;
531
+ GPULabel label;
963
532
  bool mappedAtCreation = false;
964
533
  uint64_t size = 0;
965
534
  uint32_t usage = 0;
@@ -971,10 +540,7 @@ void GPUDeviceImpl::CreateBuffer(const v8::FunctionCallbackInfo<v8::Value> &args
971
540
  v8::Local<v8::Value> labelVal;
972
541
  options->Get(context, ConvertToV8String(isolate, "label")).ToLocal(&labelVal);
973
542
 
974
- if (!labelVal.IsEmpty() && labelVal->IsString()) {
975
- label = *v8::String::Utf8Value(isolate, labelVal);
976
- }
977
-
543
+ label = GPULabel(isolate, labelVal);
978
544
  v8::Local<v8::Value> mappedAtCreationVal;
979
545
 
980
546
  options->Get(context, ConvertToV8String(isolate, "mappedAtCreation")).ToLocal(
@@ -1000,7 +566,8 @@ void GPUDeviceImpl::CreateBuffer(const v8::FunctionCallbackInfo<v8::Value> &args
1000
566
  }
1001
567
  }
1002
568
 
1003
- auto buffer = canvas_native_webgpu_device_create_buffer(ptr->GetGPUDevice(), label, size, usage,
569
+ auto buffer = canvas_native_webgpu_device_create_buffer(ptr->GetGPUDevice(), *label,
570
+ size, usage,
1004
571
  mappedAtCreation);
1005
572
 
1006
573
  if (buffer != nullptr) {
@@ -1021,15 +588,10 @@ void GPUDeviceImpl::CreateCommandEncoder(const v8::FunctionCallbackInfo<v8::Valu
1021
588
  }
1022
589
  auto isolate = args.GetIsolate();
1023
590
 
1024
- char *label = nullptr;
1025
-
1026
- auto labelVal = args[0];
591
+ auto label = GPULabel(isolate, args[0]);
1027
592
 
1028
- if (!labelVal.IsEmpty() && labelVal->IsString()) {
1029
- label = *v8::String::Utf8Value(isolate, labelVal);
1030
- }
1031
-
1032
- auto encoder = canvas_native_webgpu_device_create_command_encoder(ptr->GetGPUDevice(), label);
593
+ auto encoder = canvas_native_webgpu_device_create_command_encoder(ptr->GetGPUDevice(),
594
+ *label);
1033
595
 
1034
596
  if (encoder != nullptr) {
1035
597
  auto instance = new GPUCommandEncoderImpl(encoder);
@@ -1061,11 +623,7 @@ void GPUDeviceImpl::CreateComputePipeline(const v8::FunctionCallbackInfo<v8::Val
1061
623
  v8::Local<v8::Value> labelVal;
1062
624
  options->Get(context, ConvertToV8String(isolate, "label")).ToLocal(&labelVal);
1063
625
 
1064
- char *label = nullptr;
1065
-
1066
- if (!labelVal.IsEmpty() && labelVal->IsString()) {
1067
- label = *v8::String::Utf8Value(isolate, labelVal);
1068
- }
626
+ GPULabel label(isolate, labelVal);
1069
627
 
1070
628
  CanvasGPUPipelineLayoutOrGPUAutoLayoutMode layout{
1071
629
  CanvasGPUPipelineLayoutOrGPUAutoLayoutModeAuto
@@ -1151,7 +709,8 @@ void GPUDeviceImpl::CreateComputePipeline(const v8::FunctionCallbackInfo<v8::Val
1151
709
  };
1152
710
 
1153
711
  auto pipeline = canvas_native_webgpu_device_create_compute_pipeline(ptr->GetGPUDevice(),
1154
- label, layout, &stage);
712
+ *label, layout,
713
+ &stage);
1155
714
 
1156
715
  if (entry_point != nullptr) {
1157
716
  free(entry_point);
@@ -1174,7 +733,34 @@ void GPUDeviceImpl::CreateComputePipeline(const v8::FunctionCallbackInfo<v8::Val
1174
733
  args.GetReturnValue().SetUndefined();
1175
734
  }
1176
735
 
1177
- void GPUDeviceImpl::CreatePipelineLayout(const v8::FunctionCallbackInfo<v8::Value> &args) {
736
+ struct ComputePipeLineAsyncData {
737
+ char *label;
738
+ CanvasConstants *constants;
739
+ enum CanvasGPUErrorType type;
740
+ char *errorMessage;
741
+ const CanvasGPUComputePipeline *pipeline;
742
+
743
+ ~ComputePipeLineAsyncData() {
744
+ if (label != nullptr) {
745
+ free(label);
746
+ label = nullptr;
747
+ canvas_native_webgpu_constants_destroy(constants);
748
+ constants = nullptr;
749
+ }
750
+
751
+ if (constants != nullptr) {
752
+ canvas_native_webgpu_constants_destroy(constants);
753
+ constants = nullptr;
754
+ }
755
+
756
+ if (errorMessage != nullptr) {
757
+ canvas_native_string_destroy(errorMessage);
758
+ errorMessage = nullptr;
759
+ }
760
+ }
761
+ };
762
+
763
+ void GPUDeviceImpl::CreateComputePipelineAsync(const v8::FunctionCallbackInfo<v8::Value> &args) {
1178
764
  GPUDeviceImpl *ptr = GetPointer(args.This());
1179
765
  if (ptr == nullptr) {
1180
766
  return;
@@ -1183,6 +769,7 @@ void GPUDeviceImpl::CreatePipelineLayout(const v8::FunctionCallbackInfo<v8::Valu
1183
769
  auto context = isolate->GetCurrentContext();
1184
770
 
1185
771
  auto optionsVal = args[0];
772
+ auto callback = args[1];
1186
773
 
1187
774
  if (!optionsVal->IsObject()) {
1188
775
  // should error at this point
@@ -1193,194 +780,1411 @@ void GPUDeviceImpl::CreatePipelineLayout(const v8::FunctionCallbackInfo<v8::Valu
1193
780
  v8::Local<v8::Value> labelVal;
1194
781
  options->Get(context, ConvertToV8String(isolate, "label")).ToLocal(&labelVal);
1195
782
 
1196
- char *label = nullptr;
783
+ auto label = GPULabel(isolate, labelVal);
784
+
785
+ CanvasGPUPipelineLayoutOrGPUAutoLayoutMode layout{
786
+ CanvasGPUPipelineLayoutOrGPUAutoLayoutModeAuto
787
+ };
788
+
789
+ v8::Local<v8::Value> layoutVal;
1197
790
 
1198
- if (!labelVal.IsEmpty() && labelVal->IsString()) {
1199
- label = *v8::String::Utf8Value(isolate, labelVal);
791
+ if (options->Get(context, ConvertToV8String(isolate, "layout")).ToLocal(&layoutVal) &&
792
+ layoutVal->IsObject()) {
793
+ auto layoutImpl = GPUPipelineLayoutImpl::GetPointer(layoutVal.As<v8::Object>());
794
+ if (layoutImpl != nullptr) {
795
+ layout.tag = CanvasGPUPipelineLayoutOrGPUAutoLayoutModeLayout;
796
+ layout.layout = layoutImpl->GetPipeline();
797
+ }
1200
798
  }
1201
799
 
1202
800
 
1203
- std::vector<const CanvasGPUBindGroupLayout *> group_layouts;
801
+ v8::Local<v8::Value> computeVal;
802
+ options->Get(context, ConvertToV8String(isolate, "compute")).ToLocal(&computeVal);
1204
803
 
1205
- v8::Local<v8::Value> groupLayoutsVal;
1206
- options->Get(context, ConvertToV8String(isolate, "bindGroupLayouts")).ToLocal(&groupLayoutsVal);
804
+ if (!computeVal.IsEmpty() && computeVal->IsObject()) {
805
+
806
+ auto computeObj = computeVal.As<v8::Object>();
807
+
808
+ v8::Local<v8::Value> constantsVal;
809
+ computeObj->Get(context, ConvertToV8String(isolate, "constants")).ToLocal(
810
+ &constantsVal);
811
+
812
+ CanvasConstants *store = nullptr;
813
+
814
+ if (!constantsVal.IsEmpty() && constantsVal->IsMap()) {
815
+ auto constants = constantsVal.As<v8::Map>();
816
+ auto keyValues = constants->AsArray();
817
+ auto length = keyValues->Length();
818
+ if (length > 0) {
819
+ store = canvas_native_webgpu_constants_create();
820
+ for (int i = 0; i < length; i += 2) {
821
+ auto k = i;
822
+ auto v = k + 1;
823
+
824
+ v8::Local<v8::Value> keyVal;
825
+ keyValues->Get(context, k).ToLocal(&keyVal);
826
+ v8::Local<v8::Value> valueVal;
827
+ keyValues->Get(context, v).ToLocal(&valueVal);
828
+
829
+
830
+ if (!keyVal.IsEmpty() && keyVal->IsString() && !valueVal.IsEmpty() &&
831
+ valueVal->IsNumber()) {
832
+ auto val = ConvertFromV8String(isolate, keyVal);
833
+ canvas_native_webgpu_constants_insert(
834
+ store,
835
+ val.c_str(),
836
+ valueVal.As<v8::Number>()->Value()
837
+ );
838
+ }
839
+
840
+ }
841
+ }
842
+ }
843
+
844
+
845
+ v8::Local<v8::Value> entryPoint;
846
+ computeObj->Get(context, ConvertToV8String(isolate, "entryPoint")).ToLocal(
847
+ &entryPoint);
848
+
849
+ char *entry_point = nullptr;
850
+
851
+ if (!entryPoint.IsEmpty() && entryPoint->IsString()) {
852
+ auto ep = v8::String::Utf8Value(isolate, entryPoint);
853
+ entry_point = (char *) malloc(ep.length());
854
+ std::strcpy(entry_point, *ep);
855
+ }
856
+
857
+ v8::Local<v8::Value> moduleVal;
858
+ computeObj->Get(context, ConvertToV8String(isolate, "module")).ToLocal(&moduleVal);
859
+
860
+ auto module = GPUShaderModuleImpl::GetPointer(moduleVal.As<v8::Object>());
861
+
862
+ CanvasProgrammableStage stage{
863
+ module->GetShaderModule(),
864
+ entry_point,
865
+ store
866
+ };
867
+
868
+
869
+ auto async_callback = new AsyncCallback(isolate, callback.As<v8::Function>(),
870
+ [](bool success, void *data) {
871
+ if (data != nullptr) {
872
+
873
+ auto async_data = static_cast<AsyncCallback *>(data);
874
+ auto func = async_data->inner_.get();
875
+ if (func != nullptr &&
876
+ func->isolate_ != nullptr) {
877
+ v8::Isolate *isolate = func->isolate_;
878
+ v8::Locker locker(isolate);
879
+ v8::Isolate::Scope isolate_scope(
880
+ isolate);
881
+ v8::HandleScope handle_scope(isolate);
882
+ v8::Local<v8::Function> callback = func->callback_.Get(
883
+ isolate);
884
+ v8::Local<v8::Context> context = callback->GetCreationContextChecked();
885
+ v8::Context::Scope context_scope(
886
+ context);
887
+
888
+ ComputePipeLineAsyncData *pipelineData = nullptr;
889
+ if (func->data != nullptr) {
890
+ pipelineData = static_cast<ComputePipeLineAsyncData *>(func->data);
891
+ }
892
+
893
+ if (pipelineData == nullptr) {
894
+ // Should never happen
895
+
896
+ auto error = v8::Object::New(
897
+ isolate);
898
+ error->Set(context,
899
+ ConvertToV8String(
900
+ isolate,
901
+ "error"),
902
+ v8::Exception::Error(
903
+ ConvertToV8String(
904
+ isolate,
905
+ "Internal Error")));
906
+ error->Set(context,
907
+ ConvertToV8String(
908
+ isolate,
909
+ "type"),
910
+ v8::Uint32::NewFromUnsigned(
911
+ isolate,
912
+ (uint32_t) CanvasGPUErrorType::CanvasGPUErrorTypeInternal));
913
+
914
+
915
+ v8::Local<v8::Value> args[1] = {
916
+ error};
917
+
918
+ callback->Call(context,
919
+ context->Global(),
920
+ 1,
921
+ args); // ignore JS return value
922
+ delete static_cast<AsyncCallback *>(data);
923
+
924
+ return;
925
+ }
926
+
927
+ if (pipelineData->type !=
928
+ CanvasGPUErrorType::CanvasGPUErrorTypeNone) {
929
+
930
+ auto error = v8::Object::New(
931
+ isolate);
932
+ error->Set(context,
933
+ ConvertToV8String(
934
+ isolate,
935
+ "error"),
936
+ v8::Exception::Error(
937
+ ConvertToV8String(
938
+ isolate,
939
+ pipelineData->errorMessage)));
940
+
941
+ error->Set(context,
942
+ ConvertToV8String(
943
+ isolate,
944
+ "type"),
945
+ v8::Uint32::NewFromUnsigned(
946
+ isolate,
947
+ (uint32_t) pipelineData->type));
948
+
949
+ v8::Local<v8::Value> args[1] = {
950
+ error};
951
+
952
+ callback->Call(context,
953
+ context->Global(),
954
+ 1,
955
+ args); // ignore JS return value
956
+ } else {
957
+
958
+ auto ret = GPUComputePipelineImpl::NewInstance(
959
+ isolate,
960
+ new GPUComputePipelineImpl(
961
+ pipelineData->pipeline));
962
+
963
+ v8::Local<v8::Value> args[2] = {
964
+ v8::Null(isolate), ret};
965
+
966
+
967
+ callback->Call(context,
968
+ context->Global(),
969
+ 2,
970
+ args); // ignore JS return value
971
+ }
972
+
973
+ if (pipelineData != nullptr) {
974
+ delete pipelineData;
975
+ pipelineData = nullptr;
976
+ }
977
+
978
+ delete static_cast<AsyncCallback *>(data);
979
+ }
980
+ }
981
+ });
982
+ async_callback->inner_->data = new ComputePipeLineAsyncData{
983
+ entry_point,
984
+ store,
985
+ CanvasGPUErrorType::CanvasGPUErrorTypeNone,
986
+ nullptr,
987
+ nullptr
988
+ };
989
+ async_callback->prepare();
990
+ canvas_native_webgpu_device_create_compute_pipeline_async(ptr->GetGPUDevice(),
991
+ *label, layout, &stage,
992
+ [](const struct CanvasGPUComputePipeline *pipeline,
993
+ enum CanvasGPUErrorType type,
994
+ char *message,
995
+ void *data) {
996
+ if (data != nullptr) {
997
+ auto async_data = static_cast<AsyncCallback *>(data);
998
+ auto inner = async_data->inner_.get();
999
+ if (inner != nullptr) {
1000
+ auto pipeline_data = static_cast<ComputePipeLineAsyncData *>(inner->data);
1001
+ pipeline_data->errorMessage = message;
1002
+ pipeline_data->type = type;
1003
+ pipeline_data->pipeline = pipeline;
1004
+ async_data->execute(
1005
+ true);
1006
+ }
1007
+ }
1008
+ }, async_callback);
1009
+
1010
+
1011
+ }
1012
+
1013
+ args.GetReturnValue().SetUndefined();
1014
+ }
1015
+
1016
+ void GPUDeviceImpl::CreatePipelineLayout(const v8::FunctionCallbackInfo<v8::Value> &args) {
1017
+ GPUDeviceImpl *ptr = GetPointer(args.This());
1018
+ if (ptr == nullptr) {
1019
+ return;
1020
+ }
1021
+ auto isolate = args.GetIsolate();
1022
+ auto context = isolate->GetCurrentContext();
1023
+
1024
+ auto optionsVal = args[0];
1025
+
1026
+ if (!optionsVal->IsObject()) {
1027
+ // should error at this point
1028
+ return;
1029
+ }
1030
+ auto options = optionsVal.As<v8::Object>();
1031
+
1032
+ v8::Local<v8::Value> labelVal;
1033
+ options->Get(context, ConvertToV8String(isolate, "label")).ToLocal(&labelVal);
1034
+
1035
+ auto label = GPULabel(isolate, labelVal);
1036
+
1037
+
1038
+ std::vector<const CanvasGPUBindGroupLayout *> group_layouts;
1039
+
1040
+ v8::Local<v8::Value> groupLayoutsVal;
1041
+ options->Get(context, ConvertToV8String(isolate, "bindGroupLayouts")).ToLocal(&groupLayoutsVal);
1042
+
1043
+ if (!groupLayoutsVal.IsEmpty() && groupLayoutsVal->IsArray()) {
1044
+ auto groupLayoutsArray = groupLayoutsVal.As<v8::Array>();
1045
+ auto len = groupLayoutsArray->Length();
1046
+ for (int i = 0; i < len; i++) {
1047
+ v8::Local<v8::Value> groupVal;
1048
+ groupLayoutsArray->Get(context, i).ToLocal(&groupVal);
1049
+ if (GetNativeType(groupVal) == NativeType::GPUBindGroupLayout) {
1050
+ auto layout = GPUBindGroupLayoutImpl::GetPointer(groupVal.As<v8::Object>());
1051
+ if (layout != nullptr) {
1052
+ group_layouts.push_back(layout->GetBindGroupLayout());
1053
+ }
1054
+ }
1055
+ }
1056
+
1057
+ auto layout = canvas_native_webgpu_device_create_pipeline_layout(ptr->GetGPUDevice(),
1058
+ *label,
1059
+ group_layouts.data(),
1060
+ group_layouts.size());
1061
+
1062
+ if (layout != nullptr) {
1063
+ auto ret = GPUPipelineLayoutImpl::NewInstance(isolate,
1064
+ new GPUPipelineLayoutImpl(layout));
1065
+ args.GetReturnValue().Set(ret);
1066
+ return;
1067
+ }
1068
+ }
1069
+
1070
+
1071
+ args.GetReturnValue().SetUndefined();
1072
+ }
1073
+
1074
+ void GPUDeviceImpl::CreateQuerySet(const v8::FunctionCallbackInfo<v8::Value> &args) {
1075
+ GPUDeviceImpl *ptr = GetPointer(args.This());
1076
+ if (ptr == nullptr) {
1077
+ return;
1078
+ }
1079
+ auto isolate = args.GetIsolate();
1080
+ auto context = isolate->GetCurrentContext();
1081
+
1082
+ auto optionsVal = args[0];
1083
+
1084
+ if (!optionsVal->IsObject()) {
1085
+ // should error at this point
1086
+ return;
1087
+ }
1088
+ auto options = optionsVal.As<v8::Object>();
1089
+
1090
+ v8::Local<v8::Value> labelVal;
1091
+ options->Get(context, ConvertToV8String(isolate, "label")).ToLocal(&labelVal);
1092
+
1093
+ auto label = GPULabel(isolate, labelVal);
1094
+ v8::Local<v8::Value> typeVal;
1095
+ options->Get(context, ConvertToV8String(isolate, "type")).ToLocal(&typeVal);
1096
+
1097
+
1098
+ v8::Local<v8::Value> countVal;
1099
+ options->Get(context, ConvertToV8String(isolate, "count")).ToLocal(&countVal);
1100
+
1101
+ auto typeStr = ConvertFromV8String(isolate, typeVal);
1102
+
1103
+ const CanvasGPUQuerySet *query_set = nullptr;
1104
+ if (typeStr == "occlusion") {
1105
+ query_set = canvas_native_webgpu_device_create_query_set(ptr->GetGPUDevice(), *label,
1106
+ CanvasQueryTypeOcclusion,
1107
+ countVal->Uint32Value(
1108
+ context).FromJust());
1109
+ } else if (typeStr == "timestamp") {
1110
+ query_set = canvas_native_webgpu_device_create_query_set(ptr->GetGPUDevice(), *label,
1111
+ CanvasQueryTypeTimestamp,
1112
+ countVal->Uint32Value(
1113
+ context).FromJust());
1114
+ } else {
1115
+ // todo throw
1116
+ }
1117
+
1118
+
1119
+ if (query_set != nullptr) {
1120
+ auto ret = GPUQuerySetImpl::NewInstance(isolate, new GPUQuerySetImpl(query_set));
1121
+ args.GetReturnValue().Set(ret);
1122
+ return;
1123
+ }
1124
+
1125
+ args.GetReturnValue().SetUndefined();
1126
+
1127
+ }
1128
+
1129
+ void GPUDeviceImpl::CreateRenderBundleEncoder(const v8::FunctionCallbackInfo<v8::Value> &args) {
1130
+ GPUDeviceImpl *ptr = GetPointer(args.This());
1131
+ if (ptr == nullptr) {
1132
+ return;
1133
+ }
1134
+ auto isolate = args.GetIsolate();
1135
+ auto context = isolate->GetCurrentContext();
1136
+
1137
+ auto optionsVal = args[0];
1138
+
1139
+ if (!optionsVal->IsObject()) {
1140
+ // should error at this point
1141
+ return;
1142
+ }
1143
+ auto options = optionsVal.As<v8::Object>();
1144
+
1145
+ v8::Local<v8::Value> labelVal;
1146
+ options->Get(context, ConvertToV8String(isolate, "label")).ToLocal(&labelVal);
1147
+
1148
+ auto label = GPULabel(isolate, labelVal);
1149
+
1150
+ std::vector<CanvasGPUTextureFormat> colorFormats;
1151
+
1152
+ v8::Local<v8::Value> colorFormatsVal;
1153
+ options->Get(context, ConvertToV8String(isolate, "colorFormats")).ToLocal(&colorFormatsVal);
1154
+
1155
+ if (!colorFormatsVal.IsEmpty() && colorFormatsVal->IsArray()) {
1156
+ auto colorFormatsArray = colorFormatsVal.As<v8::Array>();
1157
+ auto len = colorFormatsArray->Length();
1158
+ for (int i = 0; i < len; i++) {
1159
+ v8::Local<v8::Value> formatVal;
1160
+ colorFormatsArray->Get(context, i).ToLocal(&formatVal);
1161
+ if (!formatVal.IsEmpty() && formatVal->IsString()) {
1162
+ auto formatStr = ConvertFromV8String(isolate, formatVal);
1163
+ auto format = canvas_native_webgpu_enum_string_to_gpu_texture(formatStr.c_str());
1164
+ if (format.tag == CanvasOptionalGPUTextureFormatSome) {
1165
+ colorFormats.push_back(format.some);
1166
+ }
1167
+ }
1168
+
1169
+ }
1170
+ }
1171
+
1172
+
1173
+ auto depthStencilFormat = CanvasOptionalGPUTextureFormat{
1174
+ CanvasOptionalGPUTextureFormatNone
1175
+ };
1176
+
1177
+ v8::Local<v8::Value> depthStencilFormatVal;
1178
+ options->Get(context, ConvertToV8String(isolate, "depthStencilFormat")).ToLocal(
1179
+ &depthStencilFormatVal);
1180
+
1181
+ if (!depthStencilFormatVal.IsEmpty() && depthStencilFormatVal->IsString()) {
1182
+ auto depthStencilFormatStr = ConvertFromV8String(isolate, depthStencilFormatVal);
1183
+ depthStencilFormat = canvas_native_webgpu_enum_string_to_gpu_texture(
1184
+ depthStencilFormatStr.c_str());
1185
+ }
1186
+
1187
+ uint32_t sampleCount = 1;
1188
+
1189
+ bool depthReadOnly = false;
1190
+
1191
+ bool stencilReadOnly = false;
1192
+
1193
+ CanvasCreateRenderBundleEncoderDescriptor descriptor{
1194
+ *label,
1195
+ colorFormats.data(),
1196
+ colorFormats.size(),
1197
+ depthStencilFormat,
1198
+ sampleCount,
1199
+ depthReadOnly,
1200
+ stencilReadOnly
1201
+ };
1202
+
1203
+
1204
+ auto encoder = canvas_native_webgpu_device_create_render_bundle_encoder(ptr->GetGPUDevice(),
1205
+ &descriptor);
1206
+
1207
+ if (encoder != nullptr) {
1208
+ auto ret = GPURenderBundleEncoderImpl::NewInstance(isolate,
1209
+ new GPURenderBundleEncoderImpl(encoder));
1210
+ args.GetReturnValue().Set(ret);
1211
+ return;
1212
+ }
1213
+
1214
+ args.GetReturnValue().SetUndefined();
1215
+ }
1216
+
1217
+ struct RenderPipeLineAsyncData {
1218
+ char *label;
1219
+ char *vertex_entry_point;
1220
+ char *fragment_entry_point;
1221
+ CanvasConstants *constants;
1222
+ enum CanvasGPUErrorType type;
1223
+ char *errorMessage;
1224
+ const CanvasGPURenderPipeline *pipeline;
1225
+ CanvasPrimitiveState *primitive;
1226
+ CanvasMultisampleState *multisample;
1227
+ CanvasDepthStencilState *depth_stencil;
1228
+ CanvasConstants *vertex_constants;
1229
+
1230
+ ~RenderPipeLineAsyncData() {
1231
+ if (label != nullptr) {
1232
+ free(label);
1233
+ label = nullptr;
1234
+ }
1235
+
1236
+ if (constants != nullptr) {
1237
+ canvas_native_webgpu_constants_destroy(constants);
1238
+ constants = nullptr;
1239
+ }
1240
+
1241
+ if (errorMessage != nullptr) {
1242
+ canvas_native_string_destroy(errorMessage);
1243
+ errorMessage = nullptr;
1244
+ }
1245
+
1246
+ if (primitive != nullptr) {
1247
+ delete primitive;
1248
+ primitive = nullptr;
1249
+ }
1250
+
1251
+ if (multisample != nullptr) {
1252
+ delete multisample;
1253
+ multisample = nullptr;
1254
+ }
1255
+
1256
+ if (vertex_entry_point != nullptr) {
1257
+ free(vertex_entry_point);
1258
+ vertex_entry_point = nullptr;
1259
+ }
1260
+
1261
+ if (fragment_entry_point != nullptr) {
1262
+ free(fragment_entry_point);
1263
+ fragment_entry_point = nullptr;
1264
+ }
1265
+
1266
+ if (depth_stencil != nullptr) {
1267
+ delete depth_stencil;
1268
+ depth_stencil = nullptr;
1269
+ }
1270
+
1271
+ if (vertex_constants != nullptr) {
1272
+ canvas_native_webgpu_constants_destroy(vertex_constants);
1273
+ vertex_constants = nullptr;
1274
+ }
1275
+ }
1276
+ };
1277
+
1278
+ void GPUDeviceImpl::CreateRenderPipeline(const v8::FunctionCallbackInfo<v8::Value> &args) {
1279
+ GPUDeviceImpl *ptr = GetPointer(args.This());
1280
+ if (ptr == nullptr) {
1281
+ return;
1282
+ }
1283
+ auto isolate = args.GetIsolate();
1284
+ auto context = isolate->GetCurrentContext();
1285
+
1286
+ CanvasCreateRenderPipelineDescriptor descriptor{};
1287
+ descriptor.label = nullptr;
1288
+
1289
+ auto optionsVal = args[0];
1290
+
1291
+ if (!optionsVal->IsObject()) {
1292
+ // should error at this point
1293
+ return;
1294
+ }
1295
+ auto options = optionsVal.As<v8::Object>();
1296
+
1297
+ v8::Local<v8::Value> stencilValue;
1298
+ auto hasDepthStencil = options->Get(context, ConvertToV8String(isolate, "depthStencil")).ToLocal(
1299
+ &stencilValue);
1300
+
1301
+ CanvasDepthStencilState *stencil = nullptr;
1302
+
1303
+ if (hasDepthStencil && stencilValue->IsObject()) {
1304
+ auto stencilObj = stencilValue.As<v8::Object>();
1305
+ stencil = new CanvasDepthStencilState{};
1306
+ stencil->depth_bias = 0;
1307
+ stencil->depth_bias_clamp = 0;
1308
+ stencil->depth_bias_slope_scale = 0;
1309
+ stencil->stencil_read_mask = 0xFFFFFFFF;
1310
+ stencil->stencil_write_mask = 0xFFFFFFFF;
1311
+ stencil->stencil_front = CanvasStencilFaceState{
1312
+ CanvasCompareFunctionAlways,
1313
+ CanvasStencilOperationKeep,
1314
+ CanvasStencilOperationKeep,
1315
+ CanvasStencilOperationKeep
1316
+ };
1317
+
1318
+ stencil->stencil_back = CanvasStencilFaceState{
1319
+ CanvasCompareFunctionAlways,
1320
+ CanvasStencilOperationKeep,
1321
+ CanvasStencilOperationKeep,
1322
+ CanvasStencilOperationKeep
1323
+ };
1324
+ // todo throw if failed
1325
+ v8::Local<v8::Value> formatValue;
1326
+
1327
+ stencilObj->Get(context, ConvertToV8String(isolate, "format")).ToLocal(&formatValue);
1328
+ if (!formatValue.IsEmpty() && formatValue->IsString()) {
1329
+ auto val = ConvertFromV8String(isolate, formatValue);
1330
+ auto format = canvas_native_webgpu_enum_string_to_gpu_texture(
1331
+ val.c_str());
1332
+ if (format.tag ==
1333
+ CanvasOptionalGPUTextureFormat_Tag::CanvasOptionalGPUTextureFormatSome) {
1334
+ stencil->format = format.some;
1335
+ }
1336
+ } else {
1337
+ // todo throw
1338
+ }
1339
+
1340
+ v8::Local<v8::Value> depthBiasVal;
1341
+ stencilObj->Get(context, ConvertToV8String(isolate, "depthBias")).ToLocal(&depthBiasVal);
1342
+
1343
+ if (!depthBiasVal.IsEmpty() && depthBiasVal->IsInt32()) {
1344
+ stencil->depth_bias = depthBiasVal->Int32Value(context).FromJust();
1345
+ }
1346
+
1347
+ v8::Local<v8::Value> depthBiasClampVal;
1348
+ stencilObj->Get(context, ConvertToV8String(isolate, "depthBiasClamp")).ToLocal(
1349
+ &depthBiasClampVal);
1350
+
1351
+ if (!depthBiasClampVal.IsEmpty() && depthBiasClampVal->IsNumber()) {
1352
+ stencil->depth_bias_clamp = (float) depthBiasClampVal->NumberValue(context).FromJust();
1353
+ }
1354
+
1355
+
1356
+ v8::Local<v8::Value> depthBiasSlopeScaleVal;
1357
+ stencilObj->Get(context, ConvertToV8String(isolate, "depthBiasSlopeScale")).ToLocal(
1358
+ &depthBiasSlopeScaleVal);
1359
+
1360
+ if (!depthBiasSlopeScaleVal.IsEmpty() && depthBiasSlopeScaleVal->IsNumber()) {
1361
+ stencil->depth_bias_slope_scale = (float) depthBiasSlopeScaleVal->NumberValue(
1362
+ context).FromJust();
1363
+ }
1364
+
1365
+ v8::Local<v8::Value> depthCompareVal;
1366
+ stencilObj->Get(context, ConvertToV8String(isolate, "depthCompare")).ToLocal(
1367
+ &depthCompareVal);
1368
+
1369
+ auto depthCompareStr = ConvertFromV8String(isolate, depthCompareVal);
1370
+
1371
+ if (depthCompareStr == "never") {
1372
+ stencil->depth_compare = CanvasCompareFunctionNever;
1373
+ } else if (depthCompareStr == "less") {
1374
+ stencil->depth_compare = CanvasCompareFunctionLess;
1375
+ } else if (depthCompareStr == "equal") {
1376
+ stencil->depth_compare = CanvasCompareFunctionEqual;
1377
+ } else if (depthCompareStr == "less-equal") {
1378
+ stencil->depth_compare = CanvasCompareFunctionLessEqual;
1379
+ } else if (depthCompareStr == "greater") {
1380
+ stencil->depth_compare = CanvasCompareFunctionGreater;
1381
+ } else if (depthCompareStr == "not-equal") {
1382
+ stencil->depth_compare = CanvasCompareFunctionNotEqual;
1383
+ } else if (depthCompareStr == "greater-equal") {
1384
+ stencil->depth_compare = CanvasCompareFunctionGreaterEqual;
1385
+ } else if (depthCompareStr == "always") {
1386
+ stencil->depth_compare = CanvasCompareFunctionAlways;
1387
+ }
1388
+
1389
+ stencil->depth_write_enabled = stencilObj->Get(context, ConvertToV8String(isolate,
1390
+ "depthWriteEnabled")).ToLocalChecked()->BooleanValue(
1391
+ isolate);
1392
+
1393
+
1394
+ v8::Local<v8::Value> stencilBackVal;
1395
+ stencilObj->Get(context, ConvertToV8String(isolate, "stencilBack")).ToLocal(
1396
+ &stencilBackVal);
1397
+
1398
+ if (!stencilBackVal.IsEmpty() && stencilBackVal->IsObject()) {
1399
+ auto stencilBackObj = stencilBackVal.As<v8::Object>();
1400
+
1401
+ v8::Local<v8::Value> compareVal;
1402
+ stencilBackObj->Get(context, ConvertToV8String(isolate, "compare")).ToLocal(
1403
+ &compareVal);
1404
+
1405
+ stencil->stencil_back.compare = ParseCompareFunction(isolate, compareVal,
1406
+ stencil->stencil_back.compare);
1407
+
1408
+ v8::Local<v8::Value> depthFailOpVal;
1409
+ stencilBackObj->Get(context, ConvertToV8String(isolate, "depthFailOp")).ToLocal(
1410
+ &depthFailOpVal);
1411
+
1412
+ stencil->stencil_back.depth_fail_op = ParseStencilOperation(isolate, depthFailOpVal,
1413
+ stencil->stencil_back.depth_fail_op);
1414
+
1415
+
1416
+ v8::Local<v8::Value> failOpVal;
1417
+ stencilBackObj->Get(context, ConvertToV8String(isolate, "failOp")).ToLocal(
1418
+ &failOpVal);
1419
+
1420
+ stencil->stencil_back.fail_op = ParseStencilOperation(isolate, failOpVal,
1421
+ stencil->stencil_back.fail_op);
1422
+
1423
+ v8::Local<v8::Value> passOpVal;
1424
+ stencilBackObj->Get(context, ConvertToV8String(isolate, "passOp")).ToLocal(
1425
+ &passOpVal);
1426
+
1427
+ stencil->stencil_back.pass_op = ParseStencilOperation(isolate, passOpVal,
1428
+ stencil->stencil_back.pass_op);
1429
+
1430
+ }
1431
+
1432
+
1433
+ v8::Local<v8::Value> stencilFrontVal;
1434
+ stencilObj->Get(context, ConvertToV8String(isolate, "stencilFront")).ToLocal(
1435
+ &stencilFrontVal);
1436
+
1437
+ if (!stencilFrontVal.IsEmpty() && stencilFrontVal->IsObject()) {
1438
+ auto stencilFrontObj = stencilFrontVal.As<v8::Object>();
1439
+
1440
+ v8::Local<v8::Value> compareVal;
1441
+ stencilFrontObj->Get(context, ConvertToV8String(isolate, "compare")).ToLocal(
1442
+ &compareVal);
1443
+
1444
+ stencil->stencil_front.compare = ParseCompareFunction(isolate, compareVal,
1445
+ stencil->stencil_front.compare);
1446
+
1447
+ v8::Local<v8::Value> depthFailOpVal;
1448
+ stencilFrontObj->Get(context, ConvertToV8String(isolate, "depthFailOp")).ToLocal(
1449
+ &depthFailOpVal);
1450
+
1451
+ stencil->stencil_front.depth_fail_op = ParseStencilOperation(isolate, depthFailOpVal,
1452
+ stencil->stencil_front.depth_fail_op);
1453
+
1454
+
1455
+ v8::Local<v8::Value> failOpVal;
1456
+ stencilFrontObj->Get(context, ConvertToV8String(isolate, "failOp")).ToLocal(
1457
+ &failOpVal);
1458
+
1459
+ stencil->stencil_front.fail_op = ParseStencilOperation(isolate, failOpVal,
1460
+ stencil->stencil_front.fail_op);
1461
+
1462
+ v8::Local<v8::Value> passOpVal;
1463
+ stencilFrontObj->Get(context, ConvertToV8String(isolate, "passOp")).ToLocal(
1464
+ &passOpVal);
1465
+
1466
+ stencil->stencil_front.pass_op = ParseStencilOperation(isolate, passOpVal,
1467
+ stencil->stencil_front.pass_op);
1468
+
1469
+ }
1470
+
1471
+ v8::Local<v8::Value> stencilReadMaskVal;
1472
+ stencilObj->Get(context, ConvertToV8String(isolate, "stencilReadMask")).ToLocal(
1473
+ &stencilReadMaskVal);
1474
+
1475
+ if (!stencilReadMaskVal.IsEmpty() && stencilReadMaskVal->IsUint32()) {
1476
+ stencil->stencil_read_mask = stencilReadMaskVal->Uint32Value(context).FromJust();
1477
+ }
1478
+
1479
+
1480
+ v8::Local<v8::Value> stencilWriteMaskVal;
1481
+ stencilObj->Get(context, ConvertToV8String(isolate, "stencilWriteMask")).ToLocal(
1482
+ &stencilWriteMaskVal);
1483
+
1484
+ if (!stencilWriteMaskVal.IsEmpty() && stencilWriteMaskVal->IsUint32()) {
1485
+ stencil->stencil_write_mask = stencilWriteMaskVal->Uint32Value(context).FromJust();
1486
+ }
1487
+
1488
+ descriptor.depth_stencil = stencil;
1489
+
1490
+ }
1491
+
1492
+
1493
+ v8::Local<v8::Value> fragmentValue;
1494
+ auto hasFragment = options->Get(context, ConvertToV8String(isolate, "fragment")).ToLocal(
1495
+ &fragmentValue);
1496
+
1497
+ CanvasFragmentState *fragment = nullptr;
1498
+
1499
+ std::vector<CanvasColorTargetState> targets;
1500
+
1501
+ if (hasFragment && fragmentValue->IsObject()) {
1502
+ auto fragmentValueObj = fragmentValue.As<v8::Object>();
1503
+ fragment = new CanvasFragmentState{};
1504
+ fragment->entry_point = nullptr;
1505
+
1506
+ v8::Local<v8::Value> targetsVal;
1507
+ fragmentValueObj->Get(context, ConvertToV8String(isolate, "targets")).ToLocal(&targetsVal);
1508
+
1509
+
1510
+ auto targetsArray = targetsVal.As<v8::Array>();
1511
+ auto len = targetsArray->Length();
1512
+
1513
+ for (int i = 0; i < len; i++) {
1514
+ auto state = targetsArray->Get(context, i).ToLocalChecked().As<v8::Object>();
1515
+
1516
+ auto formatVal = state->Get(context,
1517
+ ConvertToV8String(isolate, "format")).ToLocalChecked();
1518
+ auto formatStr = ConvertFromV8String(isolate, formatVal);
1519
+ auto formatResult = canvas_native_webgpu_enum_string_to_gpu_texture(formatStr.c_str());
1520
+
1521
+
1522
+ if (formatResult.tag == CanvasOptionalGPUTextureFormatNone) {
1523
+ // todo throw
1524
+ args.GetReturnValue().SetUndefined();
1525
+ return;
1526
+ } else {}
1527
+
1528
+ auto format = CanvasGPUTextureFormat{
1529
+ formatResult.some.tag
1530
+ };
1531
+
1532
+ uint32_t writeMask = 0xF;
1533
+
1534
+ v8::Local<v8::Value> writeMaskVal;
1535
+
1536
+ auto hasWriteMask = state->Get(context, ConvertToV8String(isolate, "writeMask")).ToLocal(&writeMaskVal);
1537
+
1538
+ if (hasWriteMask && writeMaskVal->IsUint32()) {
1539
+ writeMask = writeMaskVal->Uint32Value(context).FromJust();
1540
+ }
1541
+
1542
+ CanvasOptionalBlendState blend{
1543
+ CanvasOptionalBlendStateNone
1544
+ };
1545
+
1546
+ v8::Local<v8::Value> blendVal;
1547
+
1548
+ auto hasBlend = state->Get(context, ConvertToV8String(isolate, "blend")).ToLocal(&blendVal);
1549
+
1550
+ if (hasBlend && blendVal->IsObject()) {
1551
+ auto blendObj = blendVal.As<v8::Object>();
1552
+ auto alpha = blendObj->Get(context, ConvertToV8String(isolate,
1553
+ "alpha")).ToLocalChecked().As<v8::Object>();
1554
+
1555
+ v8::Local<v8::Value> alphaSrcFactorVal;
1556
+
1557
+ alpha->Get(context,
1558
+ ConvertToV8String(isolate,
1559
+ "srcFactor")).ToLocal(&alphaSrcFactorVal);
1560
+
1561
+ auto alphaSrcFactor = ParseBlendFactor(isolate, alphaSrcFactorVal,
1562
+ CanvasBlendFactorZero);
1563
+
1564
+ v8::Local<v8::Value> alphaDstFactorVal;
1565
+ alpha->Get(context,
1566
+ ConvertToV8String(isolate,
1567
+ "dstFactor")).ToLocal(&alphaDstFactorVal);
1568
+
1569
+ auto alphaDstFactor = ParseBlendFactor(isolate, alphaDstFactorVal,
1570
+ CanvasBlendFactorZero);
1571
+
1572
+ v8::Local<v8::Value> alphaOperationVal;
1573
+
1574
+ alpha->Get(context,
1575
+ ConvertToV8String(isolate,
1576
+ "operation")).ToLocal(&alphaOperationVal);
1577
+
1578
+ auto alphaOperation = ParseBlendOperation(isolate, alphaOperationVal,
1579
+ CanvasBlendOperationAdd);
1580
+
1581
+ auto alpha_val = CanvasBlendComponent{alphaSrcFactor, alphaDstFactor,
1582
+ alphaOperation};
1583
+
1584
+ auto color = blendObj->Get(context, ConvertToV8String(isolate,
1585
+ "color")).ToLocalChecked().As<v8::Object>();
1586
+
1587
+
1588
+ v8::Local<v8::Value> colorSrcFactorVal;
1589
+
1590
+ color->Get(context,
1591
+ ConvertToV8String(isolate,
1592
+ "srcFactor")).ToLocal(&colorSrcFactorVal);
1593
+
1594
+ auto colorSrcFactor = ParseBlendFactor(isolate, colorSrcFactorVal,
1595
+ CanvasBlendFactorZero);
1596
+
1597
+ v8::Local<v8::Value> colorDstFactorVal;
1598
+ color->Get(context,
1599
+ ConvertToV8String(isolate,
1600
+ "dstFactor")).ToLocal(&colorDstFactorVal);
1601
+
1602
+ auto colorDstFactor = ParseBlendFactor(isolate, colorDstFactorVal,
1603
+ CanvasBlendFactorZero);
1604
+
1605
+ v8::Local<v8::Value> colorOperationVal;
1606
+
1607
+ color->Get(context,
1608
+ ConvertToV8String(isolate,
1609
+ "operation")).ToLocal(&colorOperationVal);
1610
+
1611
+ auto colorOperation = ParseBlendOperation(isolate, colorOperationVal,
1612
+ CanvasBlendOperationAdd);
1613
+
1614
+
1615
+ auto color_val = CanvasBlendComponent{colorSrcFactor, colorDstFactor,
1616
+ colorOperation};
1617
+
1618
+
1619
+ blend = CanvasOptionalBlendState{
1620
+ CanvasOptionalBlendStateSome,
1621
+ CanvasBlendState{
1622
+ color_val, alpha_val
1623
+ }
1624
+ };
1625
+ }
1626
+
1627
+ auto targetState = CanvasColorTargetState{
1628
+ format,
1629
+ blend,
1630
+ writeMask
1631
+ };
1632
+
1633
+ targets.push_back(targetState);
1634
+ }
1635
+
1636
+ if (!targets.empty()) {
1637
+ fragment->targets = targets.data();
1638
+ fragment->targets_size = targets.size();
1639
+ }
1640
+
1641
+ v8::Local<v8::Value> constantsVal;
1642
+ auto hasConstants = fragmentValueObj->Get(context, ConvertToV8String(isolate, "constants")).ToLocal(
1643
+ &constantsVal);
1644
+
1645
+ if (hasConstants && constantsVal->IsMap()) {
1646
+ auto constants = constantsVal.As<v8::Map>();
1647
+ auto keyValues = constants->AsArray();
1648
+ auto length = keyValues->Length();
1649
+ CanvasConstants *store = nullptr;
1650
+
1651
+ if (length > 0) {
1652
+ store = canvas_native_webgpu_constants_create();
1653
+ for (int i = 0; i < length; i += 2) {
1654
+ auto k = i;
1655
+ auto v = k + 1;
1656
+
1657
+ v8::Local<v8::Value> keyVal;
1658
+ keyValues->Get(context, k).ToLocal(&keyVal);
1659
+ v8::Local<v8::Value> valueVal;
1660
+ keyValues->Get(context, v).ToLocal(&valueVal);
1661
+
1662
+
1663
+ if (!keyVal.IsEmpty() && keyVal->IsString() && !valueVal.IsEmpty() &&
1664
+ valueVal->IsNumber()) {
1665
+ canvas_native_webgpu_constants_insert(
1666
+ store,
1667
+ *v8::String::Utf8Value(isolate, keyVal),
1668
+ valueVal.As<v8::Number>()->Value()
1669
+ );
1670
+ }
1671
+
1672
+ }
1673
+ }
1674
+ fragment->constants = store;
1675
+ }
1676
+
1677
+
1678
+ v8::Local<v8::Value> entryPoint;
1679
+ auto hasEntryPoint = fragmentValueObj->Get(context, ConvertToV8String(isolate, "entryPoint")).ToLocal(
1680
+ &entryPoint);
1681
+
1682
+
1683
+ if (hasEntryPoint && entryPoint->IsString()) {
1684
+ auto ep = v8::String::Utf8Value(isolate, entryPoint);
1685
+ char *entry_point = (char *) malloc(ep.length());
1686
+ std::strcpy(entry_point, *ep);
1687
+
1688
+ fragment->entry_point = entry_point;
1689
+ }
1690
+
1691
+
1692
+ v8::Local<v8::Value> moduleVal;
1693
+ fragmentValueObj->Get(context, ConvertToV8String(isolate, "module")).ToLocal(&moduleVal);
1694
+
1695
+ auto module = GPUShaderModuleImpl::GetPointer(moduleVal.As<v8::Object>());
1696
+
1697
+ fragment->module = module->GetShaderModule();
1698
+
1699
+ descriptor.fragment = fragment;
1700
+
1701
+ }
1702
+
1703
+
1704
+ v8::Local<v8::Value> labelVal;
1705
+ options->Get(context, ConvertToV8String(isolate, "label")).ToLocal(
1706
+ &labelVal);
1707
+
1708
+
1709
+ auto label = GPULabel(isolate, labelVal);
1710
+
1711
+ descriptor.label = *label;
1712
+
1713
+
1714
+ v8::Local<v8::Value> layoutVal;
1715
+ options->Get(context, ConvertToV8String(isolate, "layout")).ToLocal(
1716
+ &layoutVal);
1717
+
1718
+ CanvasGPUPipelineLayoutOrGPUAutoLayoutMode layout;
1719
+
1720
+ if (layoutVal->IsString()) {
1721
+ layout = CanvasGPUPipelineLayoutOrGPUAutoLayoutMode{
1722
+ CanvasGPUPipelineLayoutOrGPUAutoLayoutModeAuto
1723
+ };
1724
+ } else if (!layoutVal->IsNullOrUndefined() && layoutVal->IsObject()) {
1725
+ auto pipeline = GPUPipelineLayoutImpl::GetPointer(layoutVal.As<v8::Object>());
1726
+ layout = CanvasGPUPipelineLayoutOrGPUAutoLayoutMode{
1727
+ CanvasGPUPipelineLayoutOrGPUAutoLayoutModeLayout,
1728
+ layout.layout = pipeline->GetPipeline()
1729
+ };
1730
+ } else {
1731
+ // todo throw ?
1732
+ layout = CanvasGPUPipelineLayoutOrGPUAutoLayoutMode{
1733
+ CanvasGPUPipelineLayoutOrGPUAutoLayoutModeAuto
1734
+ };
1735
+ }
1736
+
1737
+ descriptor.layout = layout;
1738
+
1739
+
1740
+ v8::Local<v8::Value> multisampleValue;
1741
+ auto hasMultisample = options->Get(context, ConvertToV8String(isolate, "multisample")).ToLocal(
1742
+ &multisampleValue);
1743
+
1744
+
1745
+ CanvasMultisampleState *multisample = nullptr;
1746
+
1747
+ if (hasMultisample && multisampleValue->IsObject()) {
1748
+ auto multisampleObj = multisampleValue.As<v8::Object>();
1749
+ multisample = new CanvasMultisampleState{};
1750
+ multisample->alpha_to_coverage_enabled = false;
1751
+ multisample->count = 1;
1752
+ multisample->mask = 0xFFFFFFFF;
1753
+
1754
+ v8::Local<v8::Value> alphaToCoverageEnabled;
1755
+ v8::Local<v8::Value> count;
1756
+ v8::Local<v8::Value> mask;
1757
+
1758
+ auto hasAlphaToCoverageEnabled = multisampleObj->Get(context, ConvertToV8String(isolate, "alphaToCoverageEnabled")).
1759
+ ToLocal(&alphaToCoverageEnabled);
1760
+
1761
+ if (hasAlphaToCoverageEnabled && alphaToCoverageEnabled->IsBoolean()) {
1762
+ multisample->alpha_to_coverage_enabled = alphaToCoverageEnabled->BooleanValue(
1763
+ isolate);
1764
+ }
1765
+
1766
+ auto hasCount = multisampleObj->Get(context, ConvertToV8String(isolate, "count")).
1767
+ ToLocal(&count);
1768
+
1769
+ if (hasCount && count->IsUint32()) {
1770
+ multisample->count = count.As<v8::Uint32>()->Value();
1771
+ }
1772
+
1773
+ auto hasMask = multisampleObj->Get(context, ConvertToV8String(isolate, "mask")).
1774
+ ToLocal(&mask);
1775
+
1776
+ if (hasMask && mask->IsNumber()) {
1777
+ // todo verify mask
1778
+ auto maskValue = mask.As<v8::Number>()->Value();
1779
+ multisample->mask = (uint64_t) maskValue;
1780
+ }
1781
+
1782
+
1783
+ descriptor.multisample = multisample;
1784
+
1785
+ }
1786
+
1787
+
1788
+ v8::Local<v8::Value> primitiveValue;
1789
+ auto hasPrimitive = options->Get(context, ConvertToV8String(isolate, "primitive")).ToLocal(
1790
+ &primitiveValue);
1791
+
1792
+
1793
+ CanvasPrimitiveState *primitive = nullptr;
1794
+
1795
+ if (hasPrimitive && primitiveValue->IsObject()) {
1796
+ auto primitiveObj = primitiveValue.As<v8::Object>();
1797
+ primitive = new CanvasPrimitiveState{};
1798
+
1799
+ primitive->cull_mode = CanvasCullMode::CanvasCullModeNone;
1800
+ primitive->front_face = CanvasFrontFaceCcw;
1801
+ primitive->strip_index_format = CanvasOptionalIndexFormat{
1802
+ CanvasOptionalIndexFormatNone
1803
+ };
1804
+
1805
+ primitive->topology = CanvasPrimitiveTopologyTriangleList;
1806
+
1807
+ primitive->unclipped_depth = false;
1808
+
1809
+
1810
+ v8::Local<v8::Value> cullModeValue;
1811
+
1812
+ if (primitiveObj->Get(context, ConvertToV8String(isolate, "cullMode")).ToLocal(
1813
+ &cullModeValue)) {
1814
+ if (cullModeValue->IsUint32()) {
1815
+ auto cullMode = cullModeValue.As<v8::Uint32>()->Value();
1816
+
1817
+ switch (cullMode) {
1818
+ case 0:
1819
+ primitive->cull_mode = CanvasCullMode::CanvasCullModeNone;
1820
+ break;
1821
+ case 1:
1822
+ primitive->cull_mode = CanvasCullMode::CanvasCullModeFront;
1823
+ break;
1824
+ case 2:
1825
+ primitive->cull_mode = CanvasCullMode::CanvasCullModeBack;
1826
+ break;
1827
+ default:
1828
+ break;
1829
+ }
1830
+ } else if (cullModeValue->IsString()) {
1831
+
1832
+ auto cullMode = ConvertFromV8String(isolate, cullModeValue);
1833
+
1834
+ if (cullMode == "none") {
1835
+ primitive->cull_mode = CanvasCullMode::CanvasCullModeNone;
1836
+ } else if (cullMode == "front") {
1837
+ primitive->cull_mode = CanvasCullMode::CanvasCullModeFront;
1838
+ } else if (cullMode == "back") {
1839
+ primitive->cull_mode = CanvasCullMode::CanvasCullModeBack;
1840
+ }
1841
+ }
1842
+
1843
+ }
1844
+
1845
+ v8::Local<v8::Value> frontFaceValue;
1846
+
1847
+ if (primitiveObj->Get(context, ConvertToV8String(isolate, "frontFace")).ToLocal(
1848
+ &frontFaceValue)) {
1849
+ if (frontFaceValue->IsUint32()) {
1850
+ auto frontFace = frontFaceValue.As<v8::Uint32>()->Value();
1851
+ switch (frontFace) {
1852
+ case 0:
1853
+ primitive->front_face = CanvasFrontFace::CanvasFrontFaceCcw;
1854
+ break;
1855
+ case 1:
1856
+ primitive->front_face = CanvasFrontFace::CanvasFrontFaceCw;
1857
+ break;
1858
+ default:
1859
+ break;
1860
+ }
1861
+ } else if (frontFaceValue->IsString()) {
1862
+ auto frontFace = ConvertFromV8String(isolate, frontFaceValue);
1863
+ if (frontFace == "ccw") {
1864
+ primitive->front_face = CanvasFrontFace::CanvasFrontFaceCcw;
1865
+ } else if (frontFace == "cw") {
1866
+ primitive->front_face = CanvasFrontFace::CanvasFrontFaceCw;
1867
+ }
1868
+ }
1869
+ }
1870
+
1871
+
1872
+ v8::Local<v8::Value> stripIndexFormatValue;
1873
+
1874
+ if (primitiveObj->Get(context, ConvertToV8String(isolate, "stripIndexFormat")).ToLocal(
1875
+ &stripIndexFormatValue)) {
1876
+ if (stripIndexFormatValue->IsUint32()) {
1877
+ auto stripIndexFormat = stripIndexFormatValue.As<v8::Uint32>()->Value();
1878
+ switch (stripIndexFormat) {
1879
+ case 0:
1880
+ primitive->strip_index_format = CanvasOptionalIndexFormat{
1881
+ CanvasOptionalIndexFormatSome,
1882
+ CanvasIndexFormat::CanvasIndexFormatUint16
1883
+ };
1884
+ break;
1885
+ case 1:
1886
+ primitive->strip_index_format = CanvasOptionalIndexFormat{
1887
+ CanvasOptionalIndexFormatSome,
1888
+ CanvasIndexFormat::CanvasIndexFormatUint32
1889
+ };
1890
+ break;
1891
+ default:
1892
+ break;
1893
+ }
1894
+ } else if (stripIndexFormatValue->IsString()) {
1895
+ auto stripIndexFormat = ConvertFromV8String(isolate, stripIndexFormatValue);
1896
+
1897
+
1898
+ if (stripIndexFormat == "uint16") {
1899
+ primitive->strip_index_format = CanvasOptionalIndexFormat{
1900
+ CanvasOptionalIndexFormatSome,
1901
+ CanvasIndexFormat::CanvasIndexFormatUint16
1902
+ };
1903
+ } else if (stripIndexFormat == "uint32") {
1904
+ primitive->strip_index_format = CanvasOptionalIndexFormat{
1905
+ CanvasOptionalIndexFormatSome,
1906
+ CanvasIndexFormat::CanvasIndexFormatUint32
1907
+ };
1908
+ }
1909
+ }
1910
+ }
1911
+
1912
+
1913
+ v8::Local<v8::Value> topologyValue;
1914
+
1915
+ if (primitiveObj->Get(context, ConvertToV8String(isolate, "topology")).ToLocal(
1916
+ &topologyValue)) {
1917
+
1918
+ if (topologyValue->IsUint32()) {
1919
+ auto topology = topologyValue.As<v8::Uint32>()->Value();
1920
+ switch (topology) {
1921
+ case 0:
1922
+ primitive->topology = CanvasPrimitiveTopology::CanvasPrimitiveTopologyPointList;
1923
+ break;
1924
+ case 1:
1925
+ primitive->topology = CanvasPrimitiveTopology::CanvasPrimitiveTopologyLineList;
1926
+ break;
1927
+ case 2:
1928
+ primitive->topology = CanvasPrimitiveTopology::CanvasPrimitiveTopologyLineStrip;
1929
+ break;
1930
+ case 3:
1931
+ primitive->topology = CanvasPrimitiveTopology::CanvasPrimitiveTopologyTriangleList;
1932
+ break;
1933
+ case 4:
1934
+ primitive->topology = CanvasPrimitiveTopology::CanvasPrimitiveTopologyTriangleStrip;
1935
+ break;
1936
+ default:
1937
+ break;
1938
+ }
1939
+ } else if (topologyValue->IsString()) {
1940
+ auto topology = ConvertFromV8String(isolate, topologyValue);
1941
+ if (topology == "line-list") {
1942
+ primitive->topology = CanvasPrimitiveTopology::CanvasPrimitiveTopologyLineList;
1943
+ } else if (topology == "line-strip") {
1944
+ primitive->topology = CanvasPrimitiveTopology::CanvasPrimitiveTopologyLineStrip;
1945
+ } else if (topology == "point-list") {
1946
+ primitive->topology = CanvasPrimitiveTopology::CanvasPrimitiveTopologyPointList;
1947
+ } else if (topology == "triangle-list") {
1948
+ primitive->topology = CanvasPrimitiveTopology::CanvasPrimitiveTopologyTriangleList;
1949
+ } else if (topology == "triangle-strip") {
1950
+ primitive->topology = CanvasPrimitiveTopology::CanvasPrimitiveTopologyTriangleStrip;
1951
+ }
1952
+ }
1953
+
1954
+ }
1955
+
1956
+
1957
+ v8::Local<v8::Value> unclippedDepthValue;
1958
+ primitiveObj->Get(context, ConvertToV8String(isolate, "unclippedDepth")).ToLocal(
1959
+ &unclippedDepthValue);
1960
+
1961
+ if (!unclippedDepthValue.IsEmpty() && unclippedDepthValue->IsBoolean()) {
1962
+ primitive->unclipped_depth = unclippedDepthValue->BooleanValue(isolate);
1963
+ }
1964
+
1965
+ descriptor.primitive = primitive;
1966
+
1967
+ }
1968
+
1969
+
1970
+ v8::Local<v8::Value> vertexValue;
1971
+ auto hasVertex = options->Get(context, ConvertToV8String(isolate, "vertex")).ToLocal(
1972
+ &vertexValue);
1973
+
1974
+
1975
+ CanvasVertexState *vertex = nullptr;
1976
+
1977
+ std::vector<CanvasVertexBufferLayout> bufferLayout;
1978
+
1979
+ std::vector<std::vector<CanvasVertexAttribute>> attributes;
1980
+
1981
+ if (hasVertex && vertexValue->IsObject()) {
1982
+ auto vertexObj = vertexValue.As<v8::Object>();
1983
+ vertex = new CanvasVertexState{};
1984
+
1985
+ v8::Local<v8::Value> moduleVal;
1986
+ vertexObj->Get(context, ConvertToV8String(isolate, "module")).ToLocal(&moduleVal);
1987
+
1988
+ auto module = GPUShaderModuleImpl::GetPointer(moduleVal.As<v8::Object>());
1989
+
1990
+ vertex->module = module->GetShaderModule();
1991
+
1992
+ v8::Local<v8::Value> constantsVal;
1993
+ auto hasConstants = vertexObj->Get(context, ConvertToV8String(isolate, "constants")).ToLocal(&constantsVal);
1994
+
1995
+ if (hasConstants && constantsVal->IsMap()) {
1996
+ auto constants = constantsVal.As<v8::Map>();
1997
+ auto keyValues = constants->AsArray();
1998
+ auto len = keyValues->Length();
1999
+ CanvasConstants *store = nullptr;
2000
+
2001
+ if (len > 0) {
2002
+ store = canvas_native_webgpu_constants_create();
2003
+ for (int i = 0; i < len; i += 2) {
2004
+ auto k = i;
2005
+ auto v = k + 1;
2006
+
2007
+ v8::Local<v8::Value> keyVal;
2008
+ keyValues->Get(context, k).ToLocal(&keyVal);
2009
+ v8::Local<v8::Value> valueVal;
2010
+ keyValues->Get(context, v).ToLocal(&valueVal);
2011
+
2012
+
2013
+ if (!keyVal.IsEmpty() && keyVal->IsString() && !valueVal.IsEmpty() &&
2014
+ valueVal->IsNumber()) {
2015
+ canvas_native_webgpu_constants_insert(
2016
+ store,
2017
+ *v8::String::Utf8Value(isolate, keyVal),
2018
+ valueVal.As<v8::Number>()->Value()
2019
+ );
2020
+ }
1207
2021
 
1208
- if (!groupLayoutsVal.IsEmpty() && groupLayoutsVal->IsArray()) {
1209
- auto groupLayoutsArray = groupLayoutsVal.As<v8::Array>();
1210
- auto len = groupLayoutsArray->Length();
1211
- for (int i = 0; i < len; i++) {
1212
- v8::Local<v8::Value> groupVal;
1213
- groupLayoutsArray->Get(context, i).ToLocal(&groupVal);
1214
- if (GetNativeType(groupVal) == NativeType::GPUBindGroupLayout) {
1215
- auto layout = GPUBindGroupLayoutImpl::GetPointer(groupVal.As<v8::Object>());
1216
- if (layout != nullptr) {
1217
- group_layouts.push_back(layout->GetBindGroupLayout());
1218
2022
  }
1219
2023
  }
1220
- }
1221
2024
 
1222
- auto layout = canvas_native_webgpu_device_create_pipeline_layout(ptr->GetGPUDevice(), label,
1223
- group_layouts.data(),
1224
- group_layouts.size());
2025
+ vertex->constants = store;
1225
2026
 
1226
- if (layout != nullptr) {
1227
- auto ret = GPUPipelineLayoutImpl::NewInstance(isolate,
1228
- new GPUPipelineLayoutImpl(layout));
1229
- args.GetReturnValue().Set(ret);
1230
- return;
1231
2027
  }
1232
- }
1233
2028
 
2029
+ v8::Local<v8::Value> buffersVal;
2030
+ auto hasBuffers = vertexObj->Get(context, ConvertToV8String(isolate, "buffers")).ToLocal(&buffersVal);
1234
2031
 
1235
- args.GetReturnValue().SetUndefined();
1236
- }
2032
+ uint64_t stride = 0;
2033
+ if (hasBuffers && buffersVal->IsArray()) {
2034
+ auto buffers = buffersVal.As<v8::Array>();
2035
+ auto len = buffers->Length();
1237
2036
 
1238
- void GPUDeviceImpl::CreateQuerySet(const v8::FunctionCallbackInfo<v8::Value> &args) {
1239
- GPUDeviceImpl *ptr = GetPointer(args.This());
1240
- if (ptr == nullptr) {
1241
- return;
1242
- }
1243
- auto isolate = args.GetIsolate();
1244
- auto context = isolate->GetCurrentContext();
2037
+ for (int i = 0; i < len; i++) {
2038
+ auto buffer = buffers->Get(context, i).ToLocalChecked().As<v8::Object>();
1245
2039
 
1246
- auto optionsVal = args[0];
2040
+ v8::Local<v8::Value> arrayStride;
1247
2041
 
1248
- if (!optionsVal->IsObject()) {
1249
- // should error at this point
1250
- return;
1251
- }
1252
- auto options = optionsVal.As<v8::Object>();
2042
+ auto hasArrayStride = buffer->Get(context, ConvertToV8String(isolate, "arrayStride")).ToLocal(
2043
+ &arrayStride);
1253
2044
 
1254
- v8::Local<v8::Value> labelVal;
1255
- options->Get(context, ConvertToV8String(isolate, "label")).ToLocal(&labelVal);
2045
+ if (hasArrayStride && arrayStride->IsNumber()) {
2046
+ stride = (uint64_t) arrayStride.As<v8::Number>()->Value();
2047
+ }
1256
2048
 
1257
- char *label = nullptr;
2049
+ std::vector<CanvasVertexAttribute> attributes_;
1258
2050
 
1259
- if (!labelVal.IsEmpty() && labelVal->IsString()) {
1260
- label = *v8::String::Utf8Value(isolate, labelVal);
1261
- }
2051
+ v8::Local<v8::Value> attributesValue;
1262
2052
 
1263
- v8::Local<v8::Value> typeVal;
1264
- options->Get(context, ConvertToV8String(isolate, "type")).ToLocal(&labelVal);
2053
+ auto hasAttributes = buffer->Get(context, ConvertToV8String(isolate, "attributes")).ToLocal(
2054
+ &attributesValue);
1265
2055
 
2056
+ if (hasAttributes && attributesValue->IsArray()) {
2057
+ auto attributes_array = attributesValue.As<v8::Array>();
2058
+ auto attributes_len = attributes_array->Length();
1266
2059
 
1267
- v8::Local<v8::Value> countVal;
1268
- options->Get(context, ConvertToV8String(isolate, "count")).ToLocal(&labelVal);
2060
+ for (int j = 0; j < attributes_len; j++) {
2061
+ auto attr = attributes_array->Get(context,
2062
+ j).ToLocalChecked().As<v8::Object>();
2063
+ auto format = attr->Get(context, ConvertToV8String(isolate,
2064
+ "format")).ToLocalChecked()->Uint32Value(
2065
+ context).ToChecked();
1269
2066
 
1270
- auto typeStr = ConvertFromV8String(isolate, typeVal);
2067
+ auto offset = (uint64_t) attr->Get(context, ConvertToV8String(isolate,
2068
+ "offset")).ToLocalChecked()->NumberValue(
2069
+ context).ToChecked();
2070
+ auto shaderLocation = attr->Get(context, ConvertToV8String(isolate,
2071
+ "shaderLocation")).ToLocalChecked()->Uint32Value(
2072
+ context).ToChecked();
1271
2073
 
1272
- const CanvasGPUQuerySet *query_set = nullptr;
1273
- if (typeStr == "occlusion") {
1274
- query_set = canvas_native_webgpu_device_create_query_set(ptr->GetGPUDevice(), label,
1275
- CanvasQueryTypeOcclusion,
1276
- countVal->Uint32Value(
1277
- context).FromJust());
1278
- } else if (typeStr == "timestamp") {
1279
- query_set = canvas_native_webgpu_device_create_query_set(ptr->GetGPUDevice(), label,
1280
- CanvasQueryTypeTimestamp,
1281
- countVal->Uint32Value(
1282
- context).FromJust());
1283
- } else {
1284
- // todo throw
1285
- }
2074
+ auto attribute = CanvasVertexAttribute{
2075
+ (CanvasVertexFormat) format,
2076
+ offset,
2077
+ shaderLocation
2078
+ };
1286
2079
 
2080
+ attributes_.push_back(attribute);
2081
+ }
1287
2082
 
1288
- if (query_set != nullptr) {
1289
- auto ret = GPUQuerySetImpl::NewInstance(isolate, new GPUQuerySetImpl(query_set));
1290
- args.GetReturnValue().Set(ret);
1291
- return;
1292
- }
2083
+ attributes.push_back(attributes_);
2084
+ }
1293
2085
 
1294
- args.GetReturnValue().SetUndefined();
1295
2086
 
1296
- }
2087
+ CanvasVertexStepMode stepMode = CanvasVertexStepModeVertex;
1297
2088
 
1298
- void GPUDeviceImpl::CreateRenderBundleEncoder(const v8::FunctionCallbackInfo<v8::Value> &args) {
1299
- GPUDeviceImpl *ptr = GetPointer(args.This());
1300
- if (ptr == nullptr) {
1301
- return;
1302
- }
1303
- auto isolate = args.GetIsolate();
1304
- auto context = isolate->GetCurrentContext();
2089
+ v8::Local<v8::Value> stepModeVal;
1305
2090
 
1306
- auto optionsVal = args[0];
2091
+ buffer->Get(context, ConvertToV8String(isolate, "stepMode")).ToLocal(
2092
+ &stepModeVal);
1307
2093
 
1308
- if (!optionsVal->IsObject()) {
1309
- // should error at this point
1310
- return;
1311
- }
1312
- auto options = optionsVal.As<v8::Object>();
1313
2094
 
1314
- v8::Local<v8::Value> labelVal;
1315
- options->Get(context, ConvertToV8String(isolate, "label")).ToLocal(&labelVal);
2095
+ if (!stepModeVal.IsEmpty()) {
2096
+ if (stepModeVal->IsUint32()) {
2097
+ switch (stepModeVal.As<v8::Uint32>()->Value()) {
2098
+ case 0:
2099
+ stepMode = CanvasVertexStepMode::CanvasVertexStepModeVertex;
2100
+ break;
2101
+ case 1:
2102
+ stepMode = CanvasVertexStepMode::CanvasVertexStepModeInstance;
2103
+ break;
2104
+ }
2105
+ } else if (stepModeVal->IsString()) {
2106
+ auto stepModeStr = ConvertFromV8String(isolate, stepModeVal);
2107
+ if (stepModeStr == "vertex") {
2108
+ stepMode = CanvasVertexStepMode::CanvasVertexStepModeVertex;
2109
+ } else if (stepModeStr == "instance") {
2110
+ stepMode = CanvasVertexStepMode::CanvasVertexStepModeInstance;
2111
+ }
2112
+ }
2113
+ }
2114
+
2115
+ auto vertexBufferLayout = CanvasVertexBufferLayout{
2116
+ stride,
2117
+ stepMode,
2118
+ attributes[i].data(),
2119
+ attributes[i].size()
2120
+ };
1316
2121
 
1317
- char *label = nullptr;
2122
+ bufferLayout.push_back(vertexBufferLayout);
2123
+ }
1318
2124
 
1319
- if (!labelVal.IsEmpty() && labelVal->IsString()) {
1320
- label = *v8::String::Utf8Value(isolate, labelVal);
1321
- }
2125
+ vertex->buffers = bufferLayout.data();
2126
+ vertex->buffers_size = bufferLayout.size();
1322
2127
 
2128
+ }
1323
2129
 
1324
- std::vector<CanvasGPUTextureFormat> colorFormats;
1325
2130
 
1326
- v8::Local<v8::Value> colorFormatsVal;
1327
- options->Get(context, ConvertToV8String(isolate, "colorFormats")).ToLocal(&colorFormatsVal);
2131
+ v8::Local<v8::Value> entryPoint;
2132
+ vertexObj->Get(context, ConvertToV8String(isolate, "entryPoint")).ToLocal(&entryPoint);
1328
2133
 
1329
- if (!colorFormatsVal.IsEmpty() && colorFormatsVal->IsArray()) {
1330
- auto colorFormatsArray = colorFormatsVal.As<v8::Array>();
1331
- auto len = colorFormatsArray->Length();
1332
- for (int i = 0; i < len; i++) {
1333
- v8::Local<v8::Value> formatVal;
1334
- colorFormatsArray->Get(context, i).ToLocal(&formatVal);
1335
- if (!formatVal.IsEmpty() && formatVal->IsString()) {
1336
- auto formatStr = ConvertFromV8String(isolate, formatVal);
1337
- auto format = canvas_native_webgpu_enum_string_to_gpu_texture(formatStr.c_str());
1338
- if (format.tag == CanvasOptionalGPUTextureFormatSome) {
1339
- colorFormats.push_back(format.some);
1340
- }
1341
- }
1342
2134
 
2135
+ if (!entryPoint.IsEmpty() && entryPoint->IsString()) {
2136
+ auto ep = v8::String::Utf8Value(isolate, entryPoint);
2137
+ char *entry_point = (char *) malloc(ep.length());
2138
+ std::strcpy(entry_point, *ep);
2139
+ vertex->entry_point = entry_point;
1343
2140
  }
2141
+
2142
+ descriptor.vertex = vertex;
2143
+
1344
2144
  }
1345
2145
 
1346
2146
 
1347
- auto depthStencilFormat = CanvasOptionalGPUTextureFormat{
1348
- CanvasOptionalGPUTextureFormatNone
1349
- };
2147
+ auto pipeline = canvas_native_webgpu_device_create_render_pipeline(ptr->GetGPUDevice(),
2148
+ &descriptor);
1350
2149
 
1351
- v8::Local<v8::Value> depthStencilFormatVal;
1352
- options->Get(context, ConvertToV8String(isolate, "depthStencilFormat")).ToLocal(
1353
- &depthStencilFormatVal);
1354
2150
 
1355
- if (!depthStencilFormatVal.IsEmpty() && depthStencilFormatVal->IsString()) {
1356
- auto depthStencilFormatStr = ConvertFromV8String(isolate, depthStencilFormatVal);
1357
- depthStencilFormat = canvas_native_webgpu_enum_string_to_gpu_texture(
1358
- depthStencilFormatStr.c_str());
2151
+ if (descriptor.fragment != nullptr) {
2152
+ if (descriptor.fragment->entry_point != nullptr) {
2153
+ free((void *) descriptor.fragment->entry_point);
2154
+ }
1359
2155
  }
1360
2156
 
1361
- uint32_t sampleCount = 1;
2157
+ if (descriptor.primitive != nullptr) {
2158
+ delete descriptor.primitive;
2159
+ descriptor.primitive = nullptr;
2160
+ }
1362
2161
 
1363
- bool depthReadOnly = false;
2162
+ if (descriptor.multisample != nullptr) {
2163
+ delete descriptor.multisample;
2164
+ descriptor.multisample = nullptr;
2165
+ }
1364
2166
 
1365
- bool stencilReadOnly = false;
1366
2167
 
1367
- CanvasCreateRenderBundleEncoderDescriptor descriptor{
1368
- label,
1369
- colorFormats.data(),
1370
- colorFormats.size(),
1371
- depthStencilFormat,
1372
- sampleCount,
1373
- depthReadOnly,
1374
- stencilReadOnly
1375
- };
2168
+ if (descriptor.vertex != nullptr) {
2169
+ if (descriptor.vertex->constants != nullptr) {
2170
+ canvas_native_webgpu_constants_destroy(
2171
+ (CanvasConstants *) descriptor.vertex->constants);
2172
+ }
1376
2173
 
2174
+ if (descriptor.vertex->entry_point != nullptr) {
2175
+ free((void *) descriptor.vertex->entry_point);
2176
+ }
1377
2177
 
1378
- auto encoder = canvas_native_webgpu_device_create_render_bundle_encoder(ptr->GetGPUDevice(),
1379
- &descriptor);
2178
+ }
1380
2179
 
1381
- if (encoder != nullptr) {
1382
- auto ret = GPURenderBundleEncoderImpl::NewInstance(isolate,
1383
- new GPURenderBundleEncoderImpl(encoder));
2180
+ if (descriptor.depth_stencil != nullptr) {
2181
+ delete descriptor.depth_stencil;
2182
+ descriptor.depth_stencil = nullptr;
2183
+ }
2184
+
2185
+
2186
+ if (pipeline != nullptr) {
2187
+ auto ret = GPURenderPipelineImpl::NewInstance(isolate, new GPURenderPipelineImpl(pipeline));
1384
2188
  args.GetReturnValue().Set(ret);
1385
2189
  return;
1386
2190
  }
@@ -1388,7 +2192,7 @@ void GPUDeviceImpl::CreateRenderBundleEncoder(const v8::FunctionCallbackInfo<v8:
1388
2192
  args.GetReturnValue().SetUndefined();
1389
2193
  }
1390
2194
 
1391
- void GPUDeviceImpl::CreateRenderPipeline(const v8::FunctionCallbackInfo<v8::Value> &args) {
2195
+ void GPUDeviceImpl::CreateRenderPipelineAsync(const v8::FunctionCallbackInfo<v8::Value> &args) {
1392
2196
  GPUDeviceImpl *ptr = GetPointer(args.This());
1393
2197
  if (ptr == nullptr) {
1394
2198
  return;
@@ -1400,13 +2204,14 @@ void GPUDeviceImpl::CreateRenderPipeline(const v8::FunctionCallbackInfo<v8::Valu
1400
2204
  descriptor.label = nullptr;
1401
2205
 
1402
2206
  auto optionsVal = args[0];
2207
+ auto callback = args[1];
1403
2208
 
1404
2209
  if (!optionsVal->IsObject()) {
1405
2210
  // should error at this point
1406
2211
  return;
1407
2212
  }
1408
2213
  auto options = optionsVal.As<v8::Object>();
1409
-
2214
+ GPULabel label;
1410
2215
 
1411
2216
  v8::Local<v8::Value> stencilValue;
1412
2217
  options->Get(context, ConvertToV8String(isolate, "depthStencil")).ToLocal(
@@ -1615,6 +2420,7 @@ void GPUDeviceImpl::CreateRenderPipeline(const v8::FunctionCallbackInfo<v8::Valu
1615
2420
  if (!fragmentValue.IsEmpty() && fragmentValue->IsObject()) {
1616
2421
  auto fragmentValueObj = fragmentValue.As<v8::Object>();
1617
2422
  fragment = new CanvasFragmentState{};
2423
+ fragment->entry_point = nullptr;
1618
2424
 
1619
2425
  v8::Local<v8::Value> targetsVal;
1620
2426
  fragmentValueObj->Get(context, ConvertToV8String(isolate, "targets")).ToLocal(&targetsVal);
@@ -1818,10 +2624,10 @@ void GPUDeviceImpl::CreateRenderPipeline(const v8::FunctionCallbackInfo<v8::Valu
1818
2624
  options->Get(context, ConvertToV8String(isolate, "label")).ToLocal(
1819
2625
  &labelVal);
1820
2626
 
2627
+ label = GPULabel(isolate, labelVal);
2628
+
2629
+ descriptor.label = *label;
1821
2630
 
1822
- if (!labelVal.IsEmpty() && labelVal->IsString()) {
1823
- descriptor.label = *v8::String::Utf8Value(isolate, labelVal);
1824
- }
1825
2631
 
1826
2632
 
1827
2633
  v8::Local<v8::Value> layoutVal;
@@ -2094,6 +2900,7 @@ void GPUDeviceImpl::CreateRenderPipeline(const v8::FunctionCallbackInfo<v8::Valu
2094
2900
  if (!vertexValue.IsEmpty() && vertexValue->IsObject()) {
2095
2901
  auto vertexObj = vertexValue.As<v8::Object>();
2096
2902
  vertex = new CanvasVertexState{};
2903
+ vertex->entry_point = nullptr;
2097
2904
 
2098
2905
  v8::Local<v8::Value> moduleVal;
2099
2906
  vertexObj->Get(context, ConvertToV8String(isolate, "module")).ToLocal(&moduleVal);
@@ -2256,50 +3063,176 @@ void GPUDeviceImpl::CreateRenderPipeline(const v8::FunctionCallbackInfo<v8::Valu
2256
3063
 
2257
3064
  }
2258
3065
 
3066
+ auto async_callback = new AsyncCallback(isolate, callback.As<v8::Function>(),
3067
+ [](bool success, void *data) {
3068
+ if (data != nullptr) {
3069
+ auto async_data = static_cast<AsyncCallback *>(data);
3070
+ auto func = async_data->inner_.get();
3071
+ if (func != nullptr &&
3072
+ func->isolate_ != nullptr) {
3073
+ v8::Isolate *isolate = func->isolate_;
3074
+ v8::Locker locker(isolate);
3075
+ v8::Isolate::Scope isolate_scope(
3076
+ isolate);
3077
+ v8::HandleScope handle_scope(isolate);
3078
+ v8::Local<v8::Function> callback = func->callback_.Get(
3079
+ isolate);
3080
+ v8::Local<v8::Context> context = callback->GetCreationContextChecked();
3081
+ v8::Context::Scope context_scope(
3082
+ context);
3083
+
3084
+ RenderPipeLineAsyncData *pipelineData = nullptr;
3085
+ if (func->data != nullptr) {
3086
+ pipelineData = static_cast<RenderPipeLineAsyncData *>(func->data);
3087
+ }
3088
+
3089
+ if (pipelineData == nullptr) {
3090
+ // Should never happen
3091
+ auto error = v8::Object::New(isolate);
3092
+ error->Set(context,
3093
+ ConvertToV8String(isolate,
3094
+ "error"),
3095
+ v8::Exception::Error(
3096
+ ConvertToV8String(
3097
+ isolate,
3098
+ "Internal Error")));
3099
+ error->Set(context, ConvertToV8String(
3100
+ isolate,
3101
+ "type"),
3102
+ v8::Uint32::NewFromUnsigned(
3103
+ isolate,
3104
+ (uint32_t) CanvasGPUErrorType::CanvasGPUErrorTypeInternal));
3105
+
3106
+ v8::Local<v8::Value> args[1] = {error};
3107
+
3108
+ callback->Call(context,
3109
+ context->Global(),
3110
+ 1,
3111
+ args); // ignore JS return value
3112
+ delete static_cast<AsyncCallback *>(data);
3113
+
3114
+ return;
3115
+ }
3116
+
3117
+ if (pipelineData->type !=
3118
+ CanvasGPUErrorType::CanvasGPUErrorTypeNone) {
3119
+
3120
+
3121
+ auto error = v8::Object::New(isolate);
3122
+ error->Set(context,
3123
+ ConvertToV8String(isolate,
3124
+ "error"),
3125
+ v8::Exception::Error(
3126
+ ConvertToV8String(
3127
+ isolate,
3128
+ pipelineData->errorMessage)));
3129
+ error->Set(context, ConvertToV8String(
3130
+ isolate,
3131
+ "type"),
3132
+ v8::Uint32::NewFromUnsigned(
3133
+ isolate,
3134
+ (uint32_t) pipelineData->type));
3135
+
3136
+ v8::Local<v8::Value> args[1] = {error};
3137
+
3138
+ callback->Call(context,
3139
+ context->Global(),
3140
+ 1,
3141
+ args); // ignore JS return value
3142
+ } else {
3143
+
3144
+ auto ret = GPURenderPipelineImpl::NewInstance(
3145
+ isolate,
3146
+ new GPURenderPipelineImpl(
3147
+ pipelineData->pipeline));
3148
+
3149
+ v8::Local<v8::Value> args[2] = {
3150
+ v8::Null(isolate), ret};
3151
+
3152
+
3153
+ callback->Call(context,
3154
+ context->Global(),
3155
+ 2,
3156
+ args); // ignore JS return value
3157
+ }
3158
+
3159
+ if (pipelineData != nullptr) {
3160
+ delete pipelineData;
3161
+ pipelineData = nullptr;
3162
+ }
3163
+
3164
+ delete static_cast<AsyncCallback *>(data);
3165
+ }
3166
+ }
3167
+ });
3168
+
3169
+ auto data = new RenderPipeLineAsyncData{
3170
+ nullptr,
3171
+ nullptr,
3172
+ nullptr,
3173
+ nullptr,
3174
+ CanvasGPUErrorType::CanvasGPUErrorTypeNone,
3175
+ nullptr,
3176
+ nullptr,
3177
+ nullptr,
3178
+ nullptr,
3179
+ nullptr,
3180
+ nullptr
3181
+ };
2259
3182
 
2260
- auto pipeline = canvas_native_webgpu_device_create_render_pipeline(ptr->GetGPUDevice(),
2261
- &descriptor);
2262
-
2263
-
2264
- if (descriptor.fragment != nullptr) {
2265
- if (descriptor.fragment->entry_point != nullptr) {
2266
- free((void *) descriptor.fragment->entry_point);
3183
+ if (fragment != nullptr) {
3184
+ if (fragment->entry_point != nullptr) {
3185
+ data->fragment_entry_point = (char *) fragment->entry_point;
2267
3186
  }
2268
3187
  }
2269
3188
 
2270
- if (descriptor.primitive != nullptr) {
2271
- delete descriptor.primitive;
3189
+ if (primitive != nullptr) {
3190
+ data->primitive = primitive;
2272
3191
  }
2273
3192
 
2274
- if (descriptor.multisample != nullptr) {
2275
- delete descriptor.multisample;
3193
+ if (multisample != nullptr) {
3194
+ data->multisample = multisample;
2276
3195
  }
2277
3196
 
2278
-
2279
- if (descriptor.vertex != nullptr) {
2280
- if (descriptor.vertex->constants != nullptr) {
2281
- canvas_native_webgpu_constants_destroy(
2282
- (CanvasConstants *) descriptor.vertex->constants);
3197
+ if (vertex != nullptr) {
3198
+ if (vertex->constants != nullptr) {
3199
+ data->vertex_constants = (CanvasConstants *) vertex->constants;
2283
3200
  }
2284
3201
 
2285
- if (descriptor.vertex->entry_point != nullptr) {
2286
- free((void *) descriptor.vertex->entry_point);
3202
+ if (vertex->entry_point != nullptr) {
3203
+ data->vertex_entry_point = (char *) descriptor.vertex->entry_point;
2287
3204
  }
2288
3205
 
2289
3206
  }
2290
3207
 
2291
- if (descriptor.depth_stencil != nullptr) {
3208
+ if (stencil != nullptr) {
2292
3209
  delete descriptor.depth_stencil;
3210
+ data->depth_stencil = stencil;
2293
3211
  }
2294
3212
 
2295
-
2296
- if (pipeline != nullptr) {
2297
- auto ret = GPURenderPipelineImpl::NewInstance(isolate, new GPURenderPipelineImpl(pipeline));
2298
- args.GetReturnValue().Set(ret);
2299
- return;
2300
- }
2301
-
2302
- args.GetReturnValue().SetUndefined();
3213
+ async_callback->inner_->data = data;
3214
+
3215
+ async_callback->prepare();
3216
+
3217
+ canvas_native_webgpu_device_create_render_pipeline_async(ptr->GetGPUDevice(),
3218
+ &descriptor, [](
3219
+ const struct CanvasGPURenderPipeline *pipeline,
3220
+ enum CanvasGPUErrorType type,
3221
+ char *message,
3222
+ void *data) {
3223
+ if (data != nullptr) {
3224
+ auto async_data = static_cast<AsyncCallback *>(data);
3225
+ auto inner = async_data->inner_.get();
3226
+ if (inner != nullptr) {
3227
+ auto pipeline_data = static_cast<RenderPipeLineAsyncData *>(inner->data);
3228
+ pipeline_data->errorMessage = message;
3229
+ pipeline_data->type = type;
3230
+ pipeline_data->pipeline = pipeline;
3231
+ async_data->execute(
3232
+ true);
3233
+ }
3234
+ }
3235
+ }, async_callback);
2303
3236
  }
2304
3237
 
2305
3238
  void GPUDeviceImpl::CreateSampler(const v8::FunctionCallbackInfo<v8::Value> &args) {
@@ -2319,11 +3252,7 @@ void GPUDeviceImpl::CreateSampler(const v8::FunctionCallbackInfo<v8::Value> &arg
2319
3252
  v8::Local<v8::Value> labelVal;
2320
3253
  options->Get(context, ConvertToV8String(isolate, "label")).ToLocal(&labelVal);
2321
3254
 
2322
- char *label = nullptr;
2323
-
2324
- if (!labelVal.IsEmpty() && labelVal->IsString()) {
2325
- label = *v8::String::Utf8Value(isolate, labelVal);
2326
- }
3255
+ GPULabel label(isolate, labelVal);
2327
3256
 
2328
3257
  auto addressModeU = CanvasAddressModeClampToEdge;
2329
3258
 
@@ -2453,12 +3382,12 @@ void GPUDeviceImpl::CreateSampler(const v8::FunctionCallbackInfo<v8::Value> &arg
2453
3382
  &maxAnisotropyVal);
2454
3383
 
2455
3384
  if (!maxAnisotropyVal.IsEmpty() && maxAnisotropyVal->IsNumber()) {
2456
- maxAnisotropy = (u_short) maxAnisotropyVal->NumberValue(context).FromJust();
3385
+ maxAnisotropy = (uint16_t) maxAnisotropyVal->NumberValue(context).FromJust();
2457
3386
  }
2458
3387
 
2459
3388
 
2460
3389
  CanvasCreateSamplerDescriptor descriptor{
2461
- label,
3390
+ *label,
2462
3391
  addressModeU,
2463
3392
  addressModeV,
2464
3393
  addressModeW,
@@ -2509,11 +3438,7 @@ void GPUDeviceImpl::CreateShaderModule(const v8::FunctionCallbackInfo<v8::Value>
2509
3438
  v8::Local<v8::Value> labelVal;
2510
3439
  desc->Get(context, ConvertToV8String(isolate, "label")).ToLocal(&labelVal);
2511
3440
 
2512
- char *label = nullptr;
2513
-
2514
- if (!labelVal.IsEmpty() && labelVal->IsString()) {
2515
- label = *v8::String::Utf8Value(isolate, labelVal);
2516
- }
3441
+ GPULabel label(isolate, labelVal);
2517
3442
 
2518
3443
  v8::Local<v8::Value> codeVal;
2519
3444
 
@@ -2523,7 +3448,8 @@ void GPUDeviceImpl::CreateShaderModule(const v8::FunctionCallbackInfo<v8::Value>
2523
3448
  code = ConvertFromV8String(isolate, codeVal);
2524
3449
  }
2525
3450
 
2526
- auto module = canvas_native_webgpu_device_create_shader_module(ptr->GetGPUDevice(), label,
3451
+ auto module = canvas_native_webgpu_device_create_shader_module(ptr->GetGPUDevice(),
3452
+ *label,
2527
3453
  code.c_str());
2528
3454
 
2529
3455
  if (module != nullptr) {
@@ -2621,7 +3547,6 @@ void GPUDeviceImpl::CreateTexture(const v8::FunctionCallbackInfo<v8::Value> &arg
2621
3547
 
2622
3548
  if (dimensionVal->IsString()) {
2623
3549
  auto dimension = ConvertFromV8String(isolate, dimensionVal);
2624
-
2625
3550
  // todo use enum
2626
3551
  if (dimension == "1d") {
2627
3552
  descriptor.dimension = CanvasTextureDimension::CanvasTextureDimensionD1;