@nativescript/canvas 2.0.0-webgpu.6 → 2.0.0-webgpu.7

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 (51) hide show
  1. package/Canvas/index.android.d.ts +0 -1
  2. package/Canvas/index.android.js +21 -22
  3. package/Canvas/index.android.js.map +1 -1
  4. package/Canvas/index.ios.js +13 -26
  5. package/Canvas/index.ios.js.map +1 -1
  6. package/Dom/Image.js +0 -1
  7. package/Dom/Image.js.map +1 -1
  8. package/WebGPU/GPUAdapter.d.ts +2 -1
  9. package/WebGPU/GPUAdapter.js.map +1 -1
  10. package/WebGPU/GPUDevice.js +22 -4
  11. package/WebGPU/GPUDevice.js.map +1 -1
  12. package/WebGPU/GPURenderPassEncoder.d.ts +1 -1
  13. package/WebGPU/GPURenderPassEncoder.js +2 -2
  14. package/WebGPU/GPURenderPassEncoder.js.map +1 -1
  15. package/WebGPU/Interfaces.d.ts +11 -1
  16. package/WebGPU/Types.d.ts +1 -0
  17. package/package.json +1 -1
  18. package/platforms/android/canvas-release.aar +0 -0
  19. package/platforms/ios/CanvasNative.xcframework/Info.plist +5 -5
  20. package/platforms/ios/CanvasNative.xcframework/ios-arm64/CanvasNative.framework/CanvasNative +0 -0
  21. package/platforms/ios/CanvasNative.xcframework/ios-arm64/CanvasNative.framework/Headers/CanvasNative-Swift.h +5 -0
  22. package/platforms/ios/CanvasNative.xcframework/ios-arm64/CanvasNative.framework/Modules/CanvasNative.swiftmodule/Project/arm64-apple-ios.swiftsourceinfo +0 -0
  23. package/platforms/ios/CanvasNative.xcframework/ios-arm64/CanvasNative.framework/Modules/CanvasNative.swiftmodule/arm64-apple-ios.abi.json +108 -0
  24. package/platforms/ios/CanvasNative.xcframework/ios-arm64/CanvasNative.framework/Modules/CanvasNative.swiftmodule/arm64-apple-ios.private.swiftinterface +3 -0
  25. package/platforms/ios/CanvasNative.xcframework/ios-arm64/CanvasNative.framework/Modules/CanvasNative.swiftmodule/arm64-apple-ios.swiftinterface +3 -0
  26. package/platforms/ios/CanvasNative.xcframework/ios-arm64/dSYMs/CanvasNative.framework.dSYM/Contents/Resources/DWARF/CanvasNative +0 -0
  27. package/platforms/ios/CanvasNative.xcframework/ios-arm64/dSYMs/CanvasNative.framework.dSYM/Contents/Resources/Relocations/aarch64/CanvasNative.yml +484 -483
  28. package/platforms/ios/CanvasNative.xcframework/ios-arm64_x86_64-simulator/CanvasNative.framework/CanvasNative +0 -0
  29. package/platforms/ios/CanvasNative.xcframework/ios-arm64_x86_64-simulator/CanvasNative.framework/Headers/CanvasNative-Swift.h +10 -0
  30. package/platforms/ios/CanvasNative.xcframework/ios-arm64_x86_64-simulator/CanvasNative.framework/Modules/CanvasNative.swiftmodule/Project/arm64-apple-ios-simulator.swiftsourceinfo +0 -0
  31. package/platforms/ios/CanvasNative.xcframework/ios-arm64_x86_64-simulator/CanvasNative.framework/Modules/CanvasNative.swiftmodule/Project/x86_64-apple-ios-simulator.swiftsourceinfo +0 -0
  32. package/platforms/ios/CanvasNative.xcframework/ios-arm64_x86_64-simulator/CanvasNative.framework/Modules/CanvasNative.swiftmodule/arm64-apple-ios-simulator.abi.json +108 -0
  33. package/platforms/ios/CanvasNative.xcframework/ios-arm64_x86_64-simulator/CanvasNative.framework/Modules/CanvasNative.swiftmodule/arm64-apple-ios-simulator.private.swiftinterface +3 -0
  34. package/platforms/ios/CanvasNative.xcframework/ios-arm64_x86_64-simulator/CanvasNative.framework/Modules/CanvasNative.swiftmodule/arm64-apple-ios-simulator.swiftinterface +3 -0
  35. package/platforms/ios/CanvasNative.xcframework/ios-arm64_x86_64-simulator/CanvasNative.framework/Modules/CanvasNative.swiftmodule/x86_64-apple-ios-simulator.abi.json +108 -0
  36. package/platforms/ios/CanvasNative.xcframework/ios-arm64_x86_64-simulator/CanvasNative.framework/Modules/CanvasNative.swiftmodule/x86_64-apple-ios-simulator.private.swiftinterface +3 -0
  37. package/platforms/ios/CanvasNative.xcframework/ios-arm64_x86_64-simulator/CanvasNative.framework/Modules/CanvasNative.swiftmodule/x86_64-apple-ios-simulator.swiftinterface +3 -0
  38. package/platforms/ios/CanvasNative.xcframework/ios-arm64_x86_64-simulator/CanvasNative.framework/_CodeSignature/CodeResources +22 -22
  39. package/platforms/ios/CanvasNative.xcframework/ios-arm64_x86_64-simulator/dSYMs/CanvasNative.framework.dSYM/Contents/Resources/DWARF/CanvasNative +0 -0
  40. package/platforms/ios/CanvasNative.xcframework/ios-arm64_x86_64-simulator/dSYMs/CanvasNative.framework.dSYM/Contents/Resources/Relocations/aarch64/CanvasNative.yml +645 -644
  41. package/platforms/ios/CanvasNative.xcframework/ios-arm64_x86_64-simulator/dSYMs/CanvasNative.framework.dSYM/Contents/Resources/Relocations/x86_64/CanvasNative.yml +683 -682
  42. package/platforms/ios/src/cpp/canvas2d/CanvasRenderingContext2DImpl.cpp +1 -1
  43. package/platforms/ios/src/cpp/canvas2d/Path2D.h +5 -5
  44. package/platforms/ios/src/cpp/webgpu/GPUAdapterImpl.cpp +2 -3
  45. package/platforms/ios/src/cpp/webgpu/GPUBindGroupImpl.h +1 -1
  46. package/platforms/ios/src/cpp/webgpu/GPUDeviceImpl.cpp +1398 -3
  47. package/platforms/ios/src/cpp/webgpu/GPUImpl.h +1 -1
  48. package/platforms/ios/src/cpp/webgpu/GPUPipelineLayoutImpl.h +1 -1
  49. package/platforms/ios/src/cpp/webgpu/GPUQuerySetImpl.h +1 -1
  50. package/platforms/ios/src/cpp/webgpu/GPUQueueImpl.cpp +0 -1
  51. package/platforms/ios/src/cpp/webgpu/GPURenderPassEncoderImpl.cpp +3 -3
@@ -103,6 +103,10 @@ v8::Local<v8::FunctionTemplate> GPUDeviceImpl::GetCtor(v8::Isolate *isolate) {
103
103
  ConvertToV8String(isolate, "createComputePipeline"),
104
104
  v8::FunctionTemplate::New(isolate, &CreateComputePipeline));
105
105
 
106
+ tmpl->Set(
107
+ ConvertToV8String(isolate, "createComputePipelineAsync"),
108
+ v8::FunctionTemplate::New(isolate, &CreateComputePipelineAsync));
109
+
106
110
  tmpl->Set(
107
111
  ConvertToV8String(isolate, "createPipelineLayout"),
108
112
  v8::FunctionTemplate::New(isolate, &CreatePipelineLayout));
@@ -119,6 +123,10 @@ v8::Local<v8::FunctionTemplate> GPUDeviceImpl::GetCtor(v8::Isolate *isolate) {
119
123
  ConvertToV8String(isolate, "createRenderPipeline"),
120
124
  v8::FunctionTemplate::New(isolate, &CreateRenderPipeline));
121
125
 
126
+ tmpl->Set(
127
+ ConvertToV8String(isolate, "createRenderPipelineAsync"),
128
+ v8::FunctionTemplate::New(isolate, &CreateRenderPipelineAsync));
129
+
122
130
  tmpl->Set(
123
131
  ConvertToV8String(isolate, "createSampler"),
124
132
  v8::FunctionTemplate::New(isolate, &CreateSampler));
@@ -416,7 +424,6 @@ void GPUDeviceImpl::CreateBindGroup(const v8::FunctionCallbackInfo<v8::Value> &a
416
424
 
417
425
  const CanvasGPUBindGroupLayout *layout = nullptr;
418
426
 
419
-
420
427
  v8::Local<v8::Value> layoutVal;
421
428
  options->Get(context, ConvertToV8String(isolate, "layout")).ToLocal(&layoutVal);
422
429
 
@@ -1174,6 +1181,289 @@ void GPUDeviceImpl::CreateComputePipeline(const v8::FunctionCallbackInfo<v8::Val
1174
1181
  args.GetReturnValue().SetUndefined();
1175
1182
  }
1176
1183
 
1184
+ struct ComputePipeLineAsyncData {
1185
+ char *label;
1186
+ CanvasConstants *constants;
1187
+ enum CanvasGPUErrorType type;
1188
+ char *errorMessage;
1189
+ const CanvasGPUComputePipeline *pipeline;
1190
+
1191
+ ~ComputePipeLineAsyncData() {
1192
+ if (label != nullptr) {
1193
+ free(label);
1194
+ label = nullptr;
1195
+ canvas_native_webgpu_constants_destroy(constants);
1196
+ constants = nullptr;
1197
+ }
1198
+
1199
+ if (constants != nullptr) {
1200
+ canvas_native_webgpu_constants_destroy(constants);
1201
+ constants = nullptr;
1202
+ }
1203
+
1204
+ if (errorMessage != nullptr) {
1205
+ canvas_native_string_destroy(errorMessage);
1206
+ errorMessage = nullptr;
1207
+ }
1208
+ }
1209
+ };
1210
+
1211
+ void GPUDeviceImpl::CreateComputePipelineAsync(const v8::FunctionCallbackInfo<v8::Value> &args) {
1212
+ GPUDeviceImpl *ptr = GetPointer(args.This());
1213
+ if (ptr == nullptr) {
1214
+ return;
1215
+ }
1216
+ auto isolate = args.GetIsolate();
1217
+ auto context = isolate->GetCurrentContext();
1218
+
1219
+ auto optionsVal = args[0];
1220
+ auto callback = args[1];
1221
+
1222
+ if (!optionsVal->IsObject()) {
1223
+ // should error at this point
1224
+ return;
1225
+ }
1226
+ auto options = optionsVal.As<v8::Object>();
1227
+
1228
+ v8::Local<v8::Value> labelVal;
1229
+ options->Get(context, ConvertToV8String(isolate, "label")).ToLocal(&labelVal);
1230
+
1231
+ char *label = nullptr;
1232
+
1233
+ if (!labelVal.IsEmpty() && labelVal->IsString()) {
1234
+ label = *v8::String::Utf8Value(isolate, labelVal);
1235
+ }
1236
+
1237
+ CanvasGPUPipelineLayoutOrGPUAutoLayoutMode layout{
1238
+ CanvasGPUPipelineLayoutOrGPUAutoLayoutModeAuto
1239
+ };
1240
+
1241
+ v8::Local<v8::Value> layoutVal;
1242
+
1243
+ if (options->Get(context, ConvertToV8String(isolate, "layout")).ToLocal(&layoutVal) && layoutVal->IsObject()) {
1244
+ auto layoutImpl = GPUPipelineLayoutImpl::GetPointer(layoutVal.As<v8::Object>());
1245
+ if (layoutImpl != nullptr) {
1246
+ layout.tag = CanvasGPUPipelineLayoutOrGPUAutoLayoutModeLayout;
1247
+ layout.layout = layoutImpl->GetPipeline();
1248
+ }
1249
+ }
1250
+
1251
+
1252
+ v8::Local<v8::Value> computeVal;
1253
+ options->Get(context, ConvertToV8String(isolate, "compute")).ToLocal(&computeVal);
1254
+
1255
+ if (!computeVal.IsEmpty() && computeVal->IsObject()) {
1256
+
1257
+ auto computeObj = computeVal.As<v8::Object>();
1258
+
1259
+ v8::Local<v8::Value> constantsVal;
1260
+ computeObj->Get(context, ConvertToV8String(isolate, "constants")).ToLocal(
1261
+ &constantsVal);
1262
+
1263
+ CanvasConstants *store = nullptr;
1264
+
1265
+ if (!constantsVal.IsEmpty() && constantsVal->IsMap()) {
1266
+ auto constants = constantsVal.As<v8::Map>();
1267
+ auto keyValues = constants->AsArray();
1268
+ auto length = keyValues->Length();
1269
+ if (length > 0) {
1270
+ store = canvas_native_webgpu_constants_create();
1271
+ for (int i = 0; i < length; i += 2) {
1272
+ auto k = i;
1273
+ auto v = k + 1;
1274
+
1275
+ v8::Local<v8::Value> keyVal;
1276
+ keyValues->Get(context, k).ToLocal(&keyVal);
1277
+ v8::Local<v8::Value> valueVal;
1278
+ keyValues->Get(context, v).ToLocal(&valueVal);
1279
+
1280
+
1281
+ if (!keyVal.IsEmpty() && keyVal->IsString() && !valueVal.IsEmpty() &&
1282
+ valueVal->IsNumber()) {
1283
+ auto val = ConvertFromV8String(isolate, keyVal);
1284
+ canvas_native_webgpu_constants_insert(
1285
+ store,
1286
+ val.c_str(),
1287
+ valueVal.As<v8::Number>()->Value()
1288
+ );
1289
+ }
1290
+
1291
+ }
1292
+ }
1293
+ }
1294
+
1295
+
1296
+ v8::Local<v8::Value> entryPoint;
1297
+ computeObj->Get(context, ConvertToV8String(isolate, "entryPoint")).ToLocal(
1298
+ &entryPoint);
1299
+
1300
+ char *entry_point = nullptr;
1301
+
1302
+ if (!entryPoint.IsEmpty() && entryPoint->IsString()) {
1303
+ auto ep = v8::String::Utf8Value(isolate, entryPoint);
1304
+ entry_point = (char *) malloc(ep.length());
1305
+ std::strcpy(entry_point, *ep);
1306
+ }
1307
+
1308
+ v8::Local<v8::Value> moduleVal;
1309
+ computeObj->Get(context, ConvertToV8String(isolate, "module")).ToLocal(&moduleVal);
1310
+
1311
+ auto module = GPUShaderModuleImpl::GetPointer(moduleVal.As<v8::Object>());
1312
+
1313
+ CanvasProgrammableStage stage{
1314
+ module->GetShaderModule(),
1315
+ entry_point,
1316
+ store
1317
+ };
1318
+
1319
+
1320
+ auto async_callback = new AsyncCallback(isolate, callback.As<v8::Function>(),
1321
+ [](bool success, void *data) {
1322
+ if (data != nullptr) {
1323
+
1324
+ auto async_data = static_cast<AsyncCallback *>(data);
1325
+ auto func = async_data->inner_.get();
1326
+ if (func != nullptr &&
1327
+ func->isolate_ != nullptr) {
1328
+ v8::Isolate *isolate = func->isolate_;
1329
+ v8::Locker locker(isolate);
1330
+ v8::Isolate::Scope isolate_scope(
1331
+ isolate);
1332
+ v8::HandleScope handle_scope(isolate);
1333
+ v8::Local<v8::Function> callback = func->callback_.Get(
1334
+ isolate);
1335
+ v8::Local<v8::Context> context = callback->GetCreationContextChecked();
1336
+ v8::Context::Scope context_scope(
1337
+ context);
1338
+
1339
+ ComputePipeLineAsyncData *pipelineData = nullptr;
1340
+ if (func->data != nullptr) {
1341
+ pipelineData = static_cast<ComputePipeLineAsyncData *>(func->data);
1342
+ }
1343
+
1344
+ if (pipelineData == nullptr) {
1345
+ // Should never happen
1346
+
1347
+ auto error = v8::Object::New(
1348
+ isolate);
1349
+ error->Set(context,
1350
+ ConvertToV8String(
1351
+ isolate,
1352
+ "error"),
1353
+ v8::Exception::Error(
1354
+ ConvertToV8String(
1355
+ isolate,
1356
+ "Internal Error")));
1357
+ error->Set(context,
1358
+ ConvertToV8String(
1359
+ isolate,
1360
+ "type"),
1361
+ v8::Uint32::NewFromUnsigned(
1362
+ isolate,
1363
+ (uint32_t) CanvasGPUErrorType::CanvasGPUErrorTypeInternal));
1364
+
1365
+
1366
+ v8::Local<v8::Value> args[1] = {
1367
+ error};
1368
+
1369
+ callback->Call(context,
1370
+ context->Global(),
1371
+ 1,
1372
+ args); // ignore JS return value
1373
+ delete static_cast<AsyncCallback *>(data);
1374
+
1375
+ return;
1376
+ }
1377
+
1378
+ if (pipelineData->type !=
1379
+ CanvasGPUErrorType::CanvasGPUErrorTypeNone) {
1380
+
1381
+ auto error = v8::Object::New(
1382
+ isolate);
1383
+ error->Set(context,
1384
+ ConvertToV8String(
1385
+ isolate,
1386
+ "error"),
1387
+ v8::Exception::Error(
1388
+ ConvertToV8String(
1389
+ isolate,
1390
+ pipelineData->errorMessage)));
1391
+
1392
+ error->Set(context,
1393
+ ConvertToV8String(
1394
+ isolate,
1395
+ "type"),
1396
+ v8::Uint32::NewFromUnsigned(
1397
+ isolate,
1398
+ (uint32_t) pipelineData->type));
1399
+
1400
+ v8::Local<v8::Value> args[1] = {
1401
+ error};
1402
+
1403
+ callback->Call(context,
1404
+ context->Global(),
1405
+ 1,
1406
+ args); // ignore JS return value
1407
+ } else {
1408
+
1409
+ auto ret = GPUComputePipelineImpl::NewInstance(
1410
+ isolate,
1411
+ new GPUComputePipelineImpl(
1412
+ pipelineData->pipeline));
1413
+
1414
+ v8::Local<v8::Value> args[2] = {
1415
+ v8::Null(isolate), ret};
1416
+
1417
+
1418
+ callback->Call(context,
1419
+ context->Global(),
1420
+ 2,
1421
+ args); // ignore JS return value
1422
+ }
1423
+
1424
+ if (pipelineData != nullptr) {
1425
+ delete pipelineData;
1426
+ pipelineData = nullptr;
1427
+ }
1428
+
1429
+ delete static_cast<AsyncCallback *>(data);
1430
+ }
1431
+ }
1432
+ });
1433
+ async_callback->inner_->data = new ComputePipeLineAsyncData{
1434
+ entry_point,
1435
+ store,
1436
+ CanvasGPUErrorType::CanvasGPUErrorTypeNone,
1437
+ nullptr,
1438
+ nullptr
1439
+ };
1440
+ async_callback->prepare();
1441
+ canvas_native_webgpu_device_create_compute_pipeline_async(ptr->GetGPUDevice(),
1442
+ label, layout, &stage,
1443
+ [](const struct CanvasGPUComputePipeline *pipeline,
1444
+ enum CanvasGPUErrorType type,
1445
+ char *message,
1446
+ void *data) {
1447
+ if (data != nullptr) {
1448
+ auto async_data = static_cast<AsyncCallback *>(data);
1449
+ auto inner = async_data->inner_.get();
1450
+ if (inner != nullptr) {
1451
+ auto pipeline_data = static_cast<ComputePipeLineAsyncData *>(inner->data);
1452
+ pipeline_data->errorMessage = message;
1453
+ pipeline_data->type = type;
1454
+ pipeline_data->pipeline = pipeline;
1455
+ async_data->execute(
1456
+ true);
1457
+ }
1458
+ }
1459
+ }, async_callback);
1460
+
1461
+
1462
+ }
1463
+
1464
+ args.GetReturnValue().SetUndefined();
1465
+ }
1466
+
1177
1467
  void GPUDeviceImpl::CreatePipelineLayout(const v8::FunctionCallbackInfo<v8::Value> &args) {
1178
1468
  GPUDeviceImpl *ptr = GetPointer(args.This());
1179
1469
  if (ptr == nullptr) {
@@ -1388,6 +1678,67 @@ void GPUDeviceImpl::CreateRenderBundleEncoder(const v8::FunctionCallbackInfo<v8:
1388
1678
  args.GetReturnValue().SetUndefined();
1389
1679
  }
1390
1680
 
1681
+ struct RenderPipeLineAsyncData {
1682
+ char *label;
1683
+ char *vertex_entry_point;
1684
+ char *fragment_entry_point;
1685
+ CanvasConstants *constants;
1686
+ enum CanvasGPUErrorType type;
1687
+ char *errorMessage;
1688
+ const CanvasGPURenderPipeline *pipeline;
1689
+ CanvasPrimitiveState *primitive;
1690
+ CanvasMultisampleState *multisample;
1691
+ CanvasDepthStencilState *depth_stencil;
1692
+ CanvasConstants *vertex_constants;
1693
+
1694
+ ~RenderPipeLineAsyncData() {
1695
+ if (label != nullptr) {
1696
+ free(label);
1697
+ label = nullptr;
1698
+ }
1699
+
1700
+ if (constants != nullptr) {
1701
+ canvas_native_webgpu_constants_destroy(constants);
1702
+ constants = nullptr;
1703
+ }
1704
+
1705
+ if (errorMessage != nullptr) {
1706
+ canvas_native_string_destroy(errorMessage);
1707
+ errorMessage = nullptr;
1708
+ }
1709
+
1710
+ if (primitive != nullptr) {
1711
+ delete primitive;
1712
+ primitive = nullptr;
1713
+ }
1714
+
1715
+ if (multisample != nullptr) {
1716
+ delete multisample;
1717
+ multisample = nullptr;
1718
+ }
1719
+
1720
+ if (vertex_entry_point != nullptr) {
1721
+ free(vertex_entry_point);
1722
+ vertex_entry_point = nullptr;
1723
+ }
1724
+
1725
+ if (fragment_entry_point != nullptr) {
1726
+ free(fragment_entry_point);
1727
+ fragment_entry_point = nullptr;
1728
+ }
1729
+
1730
+ if (depth_stencil != nullptr) {
1731
+ delete depth_stencil;
1732
+ depth_stencil = nullptr;
1733
+ }
1734
+
1735
+ if (vertex_constants != nullptr) {
1736
+ canvas_native_webgpu_constants_destroy(vertex_constants);
1737
+ vertex_constants = nullptr;
1738
+ }
1739
+ }
1740
+ };
1741
+
1391
1742
  void GPUDeviceImpl::CreateRenderPipeline(const v8::FunctionCallbackInfo<v8::Value> &args) {
1392
1743
  GPUDeviceImpl *ptr = GetPointer(args.This());
1393
1744
  if (ptr == nullptr) {
@@ -1860,7 +2211,7 @@ void GPUDeviceImpl::CreateRenderPipeline(const v8::FunctionCallbackInfo<v8::Valu
1860
2211
  if (!multisampleValue.IsEmpty() && multisampleValue->IsObject()) {
1861
2212
  auto multisampleObj = multisampleValue.As<v8::Object>();
1862
2213
  multisample = new CanvasMultisampleState{};
1863
- multisample->alpha_to_coverage_enabled = true;
2214
+ multisample->alpha_to_coverage_enabled = false;
1864
2215
  multisample->count = 1;
1865
2216
  multisample->mask = 0xFFFFFFFF;
1866
2217
 
@@ -2269,10 +2620,12 @@ void GPUDeviceImpl::CreateRenderPipeline(const v8::FunctionCallbackInfo<v8::Valu
2269
2620
 
2270
2621
  if (descriptor.primitive != nullptr) {
2271
2622
  delete descriptor.primitive;
2623
+ descriptor.primitive = nullptr;
2272
2624
  }
2273
2625
 
2274
2626
  if (descriptor.multisample != nullptr) {
2275
2627
  delete descriptor.multisample;
2628
+ descriptor.multisample = nullptr;
2276
2629
  }
2277
2630
 
2278
2631
 
@@ -2290,6 +2643,7 @@ void GPUDeviceImpl::CreateRenderPipeline(const v8::FunctionCallbackInfo<v8::Valu
2290
2643
 
2291
2644
  if (descriptor.depth_stencil != nullptr) {
2292
2645
  delete descriptor.depth_stencil;
2646
+ descriptor.depth_stencil = nullptr;
2293
2647
  }
2294
2648
 
2295
2649
 
@@ -2302,6 +2656,1047 @@ void GPUDeviceImpl::CreateRenderPipeline(const v8::FunctionCallbackInfo<v8::Valu
2302
2656
  args.GetReturnValue().SetUndefined();
2303
2657
  }
2304
2658
 
2659
+ void GPUDeviceImpl::CreateRenderPipelineAsync(const v8::FunctionCallbackInfo<v8::Value> &args) {
2660
+ GPUDeviceImpl *ptr = GetPointer(args.This());
2661
+ if (ptr == nullptr) {
2662
+ return;
2663
+ }
2664
+ auto isolate = args.GetIsolate();
2665
+ auto context = isolate->GetCurrentContext();
2666
+
2667
+ CanvasCreateRenderPipelineDescriptor descriptor{};
2668
+ descriptor.label = nullptr;
2669
+
2670
+ auto optionsVal = args[0];
2671
+ auto callback = args[1];
2672
+
2673
+ if (!optionsVal->IsObject()) {
2674
+ // should error at this point
2675
+ return;
2676
+ }
2677
+ auto options = optionsVal.As<v8::Object>();
2678
+
2679
+
2680
+ v8::Local<v8::Value> stencilValue;
2681
+ options->Get(context, ConvertToV8String(isolate, "depthStencil")).ToLocal(
2682
+ &stencilValue);
2683
+
2684
+ CanvasDepthStencilState *stencil = nullptr;
2685
+
2686
+ if (!stencilValue.IsEmpty() && stencilValue->IsObject()) {
2687
+ auto stencilObj = stencilValue.As<v8::Object>();
2688
+ stencil = new CanvasDepthStencilState{};
2689
+ stencil->depth_bias = 0;
2690
+ stencil->depth_bias_clamp = 0;
2691
+ stencil->depth_bias_slope_scale = 0;
2692
+ stencil->stencil_read_mask = 0xFFFFFFFF;
2693
+ stencil->stencil_write_mask = 0xFFFFFFFF;
2694
+ stencil->stencil_front = CanvasStencilFaceState{
2695
+ CanvasCompareFunctionAlways,
2696
+ CanvasStencilOperationKeep,
2697
+ CanvasStencilOperationKeep,
2698
+ CanvasStencilOperationKeep
2699
+ };
2700
+
2701
+ stencil->stencil_back = CanvasStencilFaceState{
2702
+ CanvasCompareFunctionAlways,
2703
+ CanvasStencilOperationKeep,
2704
+ CanvasStencilOperationKeep,
2705
+ CanvasStencilOperationKeep
2706
+ };
2707
+ // todo throw if failed
2708
+ v8::Local<v8::Value> formatValue;
2709
+
2710
+ stencilObj->Get(context, ConvertToV8String(isolate, "format")).ToLocal(&formatValue);
2711
+ if (!formatValue.IsEmpty() && formatValue->IsString()) {
2712
+ auto val = ConvertFromV8String(isolate, formatValue);
2713
+ auto format = canvas_native_webgpu_enum_string_to_gpu_texture(
2714
+ val.c_str());
2715
+ if (format.tag ==
2716
+ CanvasOptionalGPUTextureFormat_Tag::CanvasOptionalGPUTextureFormatSome) {
2717
+ stencil->format = format.some;
2718
+ }
2719
+ } else {
2720
+ // todo throw
2721
+ }
2722
+
2723
+ v8::Local<v8::Value> depthBiasVal;
2724
+ stencilObj->Get(context, ConvertToV8String(isolate, "depthBias")).ToLocal(&depthBiasVal);
2725
+
2726
+ if (!depthBiasVal.IsEmpty() && depthBiasVal->IsInt32()) {
2727
+ stencil->depth_bias = depthBiasVal->Int32Value(context).FromJust();
2728
+ }
2729
+
2730
+ v8::Local<v8::Value> depthBiasClampVal;
2731
+ stencilObj->Get(context, ConvertToV8String(isolate, "depthBiasClamp")).ToLocal(
2732
+ &depthBiasClampVal);
2733
+
2734
+ if (!depthBiasClampVal.IsEmpty() && depthBiasClampVal->IsNumber()) {
2735
+ stencil->depth_bias_clamp = (float) depthBiasClampVal->NumberValue(context).FromJust();
2736
+ }
2737
+
2738
+
2739
+ v8::Local<v8::Value> depthBiasSlopeScaleVal;
2740
+ stencilObj->Get(context, ConvertToV8String(isolate, "depthBiasSlopeScale")).ToLocal(
2741
+ &depthBiasSlopeScaleVal);
2742
+
2743
+ if (!depthBiasSlopeScaleVal.IsEmpty() && depthBiasSlopeScaleVal->IsNumber()) {
2744
+ stencil->depth_bias_slope_scale = (float) depthBiasSlopeScaleVal->NumberValue(
2745
+ context).FromJust();
2746
+ }
2747
+
2748
+ v8::Local<v8::Value> depthCompareVal;
2749
+ stencilObj->Get(context, ConvertToV8String(isolate, "depthCompare")).ToLocal(
2750
+ &depthCompareVal);
2751
+
2752
+ auto depthCompareStr = ConvertFromV8String(isolate, depthCompareVal);
2753
+
2754
+ if (depthCompareStr == "never") {
2755
+ stencil->depth_compare = CanvasCompareFunctionNever;
2756
+ } else if (depthCompareStr == "less") {
2757
+ stencil->depth_compare = CanvasCompareFunctionLess;
2758
+ } else if (depthCompareStr == "equal") {
2759
+ stencil->depth_compare = CanvasCompareFunctionEqual;
2760
+ } else if (depthCompareStr == "less-equal") {
2761
+ stencil->depth_compare = CanvasCompareFunctionLessEqual;
2762
+ } else if (depthCompareStr == "greater") {
2763
+ stencil->depth_compare = CanvasCompareFunctionGreater;
2764
+ } else if (depthCompareStr == "not-equal") {
2765
+ stencil->depth_compare = CanvasCompareFunctionNotEqual;
2766
+ } else if (depthCompareStr == "greater-equal") {
2767
+ stencil->depth_compare = CanvasCompareFunctionGreaterEqual;
2768
+ } else if (depthCompareStr == "always") {
2769
+ stencil->depth_compare = CanvasCompareFunctionAlways;
2770
+ }
2771
+
2772
+ stencil->depth_write_enabled = stencilObj->Get(context, ConvertToV8String(isolate,
2773
+ "depthWriteEnabled")).ToLocalChecked()->BooleanValue(
2774
+ isolate);
2775
+
2776
+
2777
+ v8::Local<v8::Value> stencilBackVal;
2778
+ stencilObj->Get(context, ConvertToV8String(isolate, "stencilBack")).ToLocal(
2779
+ &stencilBackVal);
2780
+
2781
+ if (!stencilBackVal.IsEmpty() && stencilBackVal->IsObject()) {
2782
+ auto stencilBackObj = stencilBackVal.As<v8::Object>();
2783
+
2784
+ v8::Local<v8::Value> compareVal;
2785
+ stencilBackObj->Get(context, ConvertToV8String(isolate, "compare")).ToLocal(
2786
+ &compareVal);
2787
+
2788
+ stencil->stencil_back.compare = ParseCompareFunction(isolate, compareVal,
2789
+ stencil->stencil_back.compare);
2790
+
2791
+ v8::Local<v8::Value> depthFailOpVal;
2792
+ stencilBackObj->Get(context, ConvertToV8String(isolate, "depthFailOp")).ToLocal(
2793
+ &depthFailOpVal);
2794
+
2795
+ stencil->stencil_back.depth_fail_op = ParseStencilOperation(isolate, depthFailOpVal,
2796
+ stencil->stencil_back.depth_fail_op);
2797
+
2798
+
2799
+ v8::Local<v8::Value> failOpVal;
2800
+ stencilBackObj->Get(context, ConvertToV8String(isolate, "failOp")).ToLocal(
2801
+ &failOpVal);
2802
+
2803
+ stencil->stencil_back.fail_op = ParseStencilOperation(isolate, failOpVal,
2804
+ stencil->stencil_back.fail_op);
2805
+
2806
+ v8::Local<v8::Value> passOpVal;
2807
+ stencilBackObj->Get(context, ConvertToV8String(isolate, "passOp")).ToLocal(
2808
+ &passOpVal);
2809
+
2810
+ stencil->stencil_back.pass_op = ParseStencilOperation(isolate, passOpVal,
2811
+ stencil->stencil_back.pass_op);
2812
+
2813
+ }
2814
+
2815
+
2816
+ v8::Local<v8::Value> stencilFrontVal;
2817
+ stencilObj->Get(context, ConvertToV8String(isolate, "stencilFront")).ToLocal(
2818
+ &stencilFrontVal);
2819
+
2820
+ if (!stencilFrontVal.IsEmpty() && stencilFrontVal->IsObject()) {
2821
+ auto stencilFrontObj = stencilFrontVal.As<v8::Object>();
2822
+
2823
+ v8::Local<v8::Value> compareVal;
2824
+ stencilFrontObj->Get(context, ConvertToV8String(isolate, "compare")).ToLocal(
2825
+ &compareVal);
2826
+
2827
+ stencil->stencil_front.compare = ParseCompareFunction(isolate, compareVal,
2828
+ stencil->stencil_front.compare);
2829
+
2830
+ v8::Local<v8::Value> depthFailOpVal;
2831
+ stencilFrontObj->Get(context, ConvertToV8String(isolate, "depthFailOp")).ToLocal(
2832
+ &depthFailOpVal);
2833
+
2834
+ stencil->stencil_front.depth_fail_op = ParseStencilOperation(isolate, depthFailOpVal,
2835
+ stencil->stencil_front.depth_fail_op);
2836
+
2837
+
2838
+ v8::Local<v8::Value> failOpVal;
2839
+ stencilFrontObj->Get(context, ConvertToV8String(isolate, "failOp")).ToLocal(
2840
+ &failOpVal);
2841
+
2842
+ stencil->stencil_front.fail_op = ParseStencilOperation(isolate, failOpVal,
2843
+ stencil->stencil_front.fail_op);
2844
+
2845
+ v8::Local<v8::Value> passOpVal;
2846
+ stencilFrontObj->Get(context, ConvertToV8String(isolate, "passOp")).ToLocal(
2847
+ &passOpVal);
2848
+
2849
+ stencil->stencil_front.pass_op = ParseStencilOperation(isolate, passOpVal,
2850
+ stencil->stencil_front.pass_op);
2851
+
2852
+ }
2853
+
2854
+ v8::Local<v8::Value> stencilReadMaskVal;
2855
+ stencilObj->Get(context, ConvertToV8String(isolate, "stencilReadMask")).ToLocal(
2856
+ &stencilReadMaskVal);
2857
+
2858
+ if (!stencilReadMaskVal.IsEmpty() && stencilReadMaskVal->IsUint32()) {
2859
+ stencil->stencil_read_mask = stencilReadMaskVal->Uint32Value(context).FromJust();
2860
+ }
2861
+
2862
+
2863
+ v8::Local<v8::Value> stencilWriteMaskVal;
2864
+ stencilObj->Get(context, ConvertToV8String(isolate, "stencilWriteMask")).ToLocal(
2865
+ &stencilWriteMaskVal);
2866
+
2867
+ if (!stencilWriteMaskVal.IsEmpty() && stencilWriteMaskVal->IsUint32()) {
2868
+ stencil->stencil_write_mask = stencilWriteMaskVal->Uint32Value(context).FromJust();
2869
+ }
2870
+
2871
+ descriptor.depth_stencil = stencil;
2872
+
2873
+ }
2874
+
2875
+
2876
+ v8::Local<v8::Value> fragmentValue;
2877
+ options->Get(context, ConvertToV8String(isolate, "fragment")).ToLocal(
2878
+ &fragmentValue);
2879
+
2880
+ CanvasFragmentState *fragment = nullptr;
2881
+
2882
+ std::vector<CanvasColorTargetState> targets;
2883
+
2884
+ if (!fragmentValue.IsEmpty() && fragmentValue->IsObject()) {
2885
+ auto fragmentValueObj = fragmentValue.As<v8::Object>();
2886
+ fragment = new CanvasFragmentState{};
2887
+
2888
+ v8::Local<v8::Value> targetsVal;
2889
+ fragmentValueObj->Get(context, ConvertToV8String(isolate, "targets")).ToLocal(&targetsVal);
2890
+
2891
+
2892
+ auto targetsArray = targetsVal.As<v8::Array>();
2893
+ auto len = targetsArray->Length();
2894
+
2895
+ for (int i = 0; i < len; i++) {
2896
+ auto state = targetsArray->Get(context, i).ToLocalChecked().As<v8::Object>();
2897
+
2898
+ auto formatVal = state->Get(context,
2899
+ ConvertToV8String(isolate, "format")).ToLocalChecked();
2900
+ auto formatStr = ConvertFromV8String(isolate, formatVal);
2901
+ auto formatResult = canvas_native_webgpu_enum_string_to_gpu_texture(formatStr.c_str());
2902
+
2903
+
2904
+ if (formatResult.tag == CanvasOptionalGPUTextureFormatNone) {
2905
+ // todo throw
2906
+ args.GetReturnValue().SetUndefined();
2907
+ return;
2908
+ } else {}
2909
+
2910
+ auto format = CanvasGPUTextureFormat{
2911
+ formatResult.some.tag
2912
+ };
2913
+
2914
+ uint32_t writeMask = 0xF;
2915
+
2916
+ v8::Local<v8::Value> writeMaskVal;
2917
+
2918
+ state->Get(context, ConvertToV8String(isolate, "writeMask")).ToLocal(&writeMaskVal);
2919
+
2920
+ if (!writeMaskVal.IsEmpty() && writeMaskVal->IsUint32()) {
2921
+ writeMask = writeMaskVal->Uint32Value(context).FromJust();
2922
+ }
2923
+
2924
+ CanvasOptionalBlendState blend{
2925
+ CanvasOptionalBlendStateNone
2926
+ };
2927
+
2928
+ v8::Local<v8::Value> blendVal;
2929
+
2930
+ state->Get(context, ConvertToV8String(isolate, "blend")).ToLocal(&blendVal);
2931
+
2932
+ if (!blendVal.IsEmpty() && blendVal->IsObject()) {
2933
+ auto blendObj = blendVal.As<v8::Object>();
2934
+ auto alpha = blendObj->Get(context, ConvertToV8String(isolate,
2935
+ "alpha")).ToLocalChecked().As<v8::Object>();
2936
+
2937
+ v8::Local<v8::Value> alphaSrcFactorVal;
2938
+
2939
+ alpha->Get(context,
2940
+ ConvertToV8String(isolate,
2941
+ "srcFactor")).ToLocal(&alphaSrcFactorVal);
2942
+
2943
+ auto alphaSrcFactor = ParseBlendFactor(isolate, alphaSrcFactorVal,
2944
+ CanvasBlendFactorZero);
2945
+
2946
+ v8::Local<v8::Value> alphaDstFactorVal;
2947
+ alpha->Get(context,
2948
+ ConvertToV8String(isolate,
2949
+ "dstFactor")).ToLocal(&alphaDstFactorVal);
2950
+
2951
+ auto alphaDstFactor = ParseBlendFactor(isolate, alphaDstFactorVal,
2952
+ CanvasBlendFactorZero);
2953
+
2954
+ v8::Local<v8::Value> alphaOperationVal;
2955
+
2956
+ alpha->Get(context,
2957
+ ConvertToV8String(isolate,
2958
+ "operation")).ToLocal(&alphaOperationVal);
2959
+
2960
+ auto alphaOperation = ParseBlendOperation(isolate, alphaOperationVal,
2961
+ CanvasBlendOperationAdd);
2962
+
2963
+ auto alpha_val = CanvasBlendComponent{alphaSrcFactor, alphaDstFactor,
2964
+ alphaOperation};
2965
+
2966
+ auto color = blendObj->Get(context, ConvertToV8String(isolate,
2967
+ "color")).ToLocalChecked().As<v8::Object>();
2968
+
2969
+
2970
+ v8::Local<v8::Value> colorSrcFactorVal;
2971
+
2972
+ color->Get(context,
2973
+ ConvertToV8String(isolate,
2974
+ "srcFactor")).ToLocal(&colorSrcFactorVal);
2975
+
2976
+ auto colorSrcFactor = ParseBlendFactor(isolate, colorSrcFactorVal,
2977
+ CanvasBlendFactorZero);
2978
+
2979
+ v8::Local<v8::Value> colorDstFactorVal;
2980
+ color->Get(context,
2981
+ ConvertToV8String(isolate,
2982
+ "dstFactor")).ToLocal(&colorDstFactorVal);
2983
+
2984
+ auto colorDstFactor = ParseBlendFactor(isolate, colorDstFactorVal,
2985
+ CanvasBlendFactorZero);
2986
+
2987
+ v8::Local<v8::Value> colorOperationVal;
2988
+
2989
+ color->Get(context,
2990
+ ConvertToV8String(isolate,
2991
+ "operation")).ToLocal(&colorOperationVal);
2992
+
2993
+ auto colorOperation = ParseBlendOperation(isolate, colorOperationVal,
2994
+ CanvasBlendOperationAdd);
2995
+
2996
+
2997
+ auto color_val = CanvasBlendComponent{colorSrcFactor, colorDstFactor,
2998
+ colorOperation};
2999
+
3000
+
3001
+ blend = CanvasOptionalBlendState{
3002
+ CanvasOptionalBlendStateSome,
3003
+ CanvasBlendState{
3004
+ color_val, alpha_val
3005
+ }
3006
+ };
3007
+ }
3008
+
3009
+ auto targetState = CanvasColorTargetState{
3010
+ format,
3011
+ blend,
3012
+ writeMask
3013
+ };
3014
+
3015
+ targets.push_back(targetState);
3016
+ }
3017
+
3018
+ if (!targets.empty()) {
3019
+ fragment->targets = targets.data();
3020
+ fragment->targets_size = targets.size();
3021
+ }
3022
+
3023
+ v8::Local<v8::Value> constantsVal;
3024
+ fragmentValueObj->Get(context, ConvertToV8String(isolate, "constants")).ToLocal(
3025
+ &constantsVal);
3026
+
3027
+ if (!constantsVal.IsEmpty() && constantsVal->IsMap()) {
3028
+ auto constants = constantsVal.As<v8::Map>();
3029
+ auto keyValues = constants->AsArray();
3030
+ auto length = keyValues->Length();
3031
+ CanvasConstants *store = nullptr;
3032
+
3033
+ if (length > 0) {
3034
+ store = canvas_native_webgpu_constants_create();
3035
+ for (int i = 0; i < length; i += 2) {
3036
+ auto k = i;
3037
+ auto v = k + 1;
3038
+
3039
+ v8::Local<v8::Value> keyVal;
3040
+ keyValues->Get(context, k).ToLocal(&keyVal);
3041
+ v8::Local<v8::Value> valueVal;
3042
+ keyValues->Get(context, v).ToLocal(&valueVal);
3043
+
3044
+
3045
+ if (!keyVal.IsEmpty() && keyVal->IsString() && !valueVal.IsEmpty() &&
3046
+ valueVal->IsNumber()) {
3047
+ canvas_native_webgpu_constants_insert(
3048
+ store,
3049
+ *v8::String::Utf8Value(isolate, keyVal),
3050
+ valueVal.As<v8::Number>()->Value()
3051
+ );
3052
+ }
3053
+
3054
+ }
3055
+ }
3056
+ fragment->constants = store;
3057
+ }
3058
+
3059
+
3060
+ v8::Local<v8::Value> entryPoint;
3061
+ fragmentValueObj->Get(context, ConvertToV8String(isolate, "entryPoint")).ToLocal(
3062
+ &entryPoint);
3063
+
3064
+
3065
+ if (!entryPoint.IsEmpty() && entryPoint->IsString()) {
3066
+ auto ep = v8::String::Utf8Value(isolate, entryPoint);
3067
+ char *entry_point = (char *) malloc(ep.length());
3068
+ std::strcpy(entry_point, *ep);
3069
+
3070
+ fragment->entry_point = entry_point;
3071
+ }
3072
+
3073
+
3074
+ v8::Local<v8::Value> moduleVal;
3075
+ fragmentValueObj->Get(context, ConvertToV8String(isolate, "module")).ToLocal(&moduleVal);
3076
+
3077
+ auto module = GPUShaderModuleImpl::GetPointer(moduleVal.As<v8::Object>());
3078
+
3079
+ fragment->module = module->GetShaderModule();
3080
+
3081
+ descriptor.fragment = fragment;
3082
+
3083
+ }
3084
+
3085
+
3086
+ v8::Local<v8::Value> labelVal;
3087
+ options->Get(context, ConvertToV8String(isolate, "label")).ToLocal(
3088
+ &labelVal);
3089
+
3090
+
3091
+ if (!labelVal.IsEmpty() && labelVal->IsString()) {
3092
+ descriptor.label = *v8::String::Utf8Value(isolate, labelVal);
3093
+ }
3094
+
3095
+
3096
+ v8::Local<v8::Value> layoutVal;
3097
+ options->Get(context, ConvertToV8String(isolate, "layout")).ToLocal(
3098
+ &layoutVal);
3099
+
3100
+ CanvasGPUPipelineLayoutOrGPUAutoLayoutMode layout;
3101
+
3102
+ if (layoutVal->IsString()) {
3103
+ layout = CanvasGPUPipelineLayoutOrGPUAutoLayoutMode{
3104
+ CanvasGPUPipelineLayoutOrGPUAutoLayoutModeAuto
3105
+ };
3106
+ } else if (!layoutVal->IsNullOrUndefined() && layoutVal->IsObject()) {
3107
+ auto pipeline = GPUPipelineLayoutImpl::GetPointer(layoutVal.As<v8::Object>());
3108
+ layout = CanvasGPUPipelineLayoutOrGPUAutoLayoutMode{
3109
+ CanvasGPUPipelineLayoutOrGPUAutoLayoutModeLayout,
3110
+ layout.layout = pipeline->GetPipeline()
3111
+ };
3112
+ } else {
3113
+ // todo throw ?
3114
+ layout = CanvasGPUPipelineLayoutOrGPUAutoLayoutMode{
3115
+ CanvasGPUPipelineLayoutOrGPUAutoLayoutModeAuto
3116
+ };
3117
+ }
3118
+
3119
+ descriptor.layout = layout;
3120
+
3121
+
3122
+ v8::Local<v8::Value> multisampleValue;
3123
+ options->Get(context, ConvertToV8String(isolate, "multisample")).ToLocal(
3124
+ &multisampleValue);
3125
+
3126
+
3127
+ CanvasMultisampleState *multisample = nullptr;
3128
+
3129
+ if (!multisampleValue.IsEmpty() && multisampleValue->IsObject()) {
3130
+ auto multisampleObj = multisampleValue.As<v8::Object>();
3131
+ multisample = new CanvasMultisampleState{};
3132
+ multisample->alpha_to_coverage_enabled = true;
3133
+ multisample->count = 1;
3134
+ multisample->mask = 0xFFFFFFFF;
3135
+
3136
+ v8::Local<v8::Value> alphaToCoverageEnabled;
3137
+ v8::Local<v8::Value> count;
3138
+ v8::Local<v8::Value> mask;
3139
+
3140
+ multisampleObj->Get(context, ConvertToV8String(isolate, "alphaToCoverageEnabled")).
3141
+ ToLocal(&alphaToCoverageEnabled);
3142
+
3143
+ if (!alphaToCoverageEnabled.IsEmpty() && alphaToCoverageEnabled->IsBoolean()) {
3144
+ multisample->alpha_to_coverage_enabled = alphaToCoverageEnabled->BooleanValue(
3145
+ isolate);
3146
+ }
3147
+
3148
+ multisampleObj->Get(context, ConvertToV8String(isolate, "count")).
3149
+ ToLocal(&count);
3150
+
3151
+ if (!count.IsEmpty() && count->IsUint32()) {
3152
+ multisample->count = count.As<v8::Uint32>()->Value();
3153
+ }
3154
+
3155
+ multisampleObj->Get(context, ConvertToV8String(isolate, "mask")).
3156
+ ToLocal(&mask);
3157
+
3158
+ if (!mask.IsEmpty() && mask->IsNumber()) {
3159
+ // todo verify mask
3160
+ auto maskValue = mask.As<v8::Number>()->Value();
3161
+ multisample->mask = (uint64_t) maskValue;
3162
+ }
3163
+
3164
+
3165
+ descriptor.multisample = multisample;
3166
+
3167
+ }
3168
+
3169
+
3170
+ v8::Local<v8::Value> primitiveValue;
3171
+ options->Get(context, ConvertToV8String(isolate, "primitive")).ToLocal(
3172
+ &primitiveValue);
3173
+
3174
+
3175
+ CanvasPrimitiveState *primitive = nullptr;
3176
+
3177
+ if (!primitiveValue.IsEmpty() && primitiveValue->IsObject()) {
3178
+ auto primitiveObj = primitiveValue.As<v8::Object>();
3179
+ primitive = new CanvasPrimitiveState{};
3180
+
3181
+ primitive->cull_mode = CanvasCullMode::CanvasCullModeNone;
3182
+ primitive->front_face = CanvasFrontFaceCcw;
3183
+ primitive->strip_index_format = CanvasOptionalIndexFormat{
3184
+ CanvasOptionalIndexFormatNone
3185
+ };
3186
+
3187
+ primitive->topology = CanvasPrimitiveTopologyTriangleList;
3188
+
3189
+ primitive->unclipped_depth = false;
3190
+
3191
+
3192
+ v8::Local<v8::Value> cullModeValue;
3193
+
3194
+ if (primitiveObj->Get(context, ConvertToV8String(isolate, "cullMode")).ToLocal(
3195
+ &cullModeValue)) {
3196
+ if (cullModeValue->IsUint32()) {
3197
+ auto cullMode = cullModeValue.As<v8::Uint32>()->Value();
3198
+
3199
+ switch (cullMode) {
3200
+ case 0:
3201
+ primitive->cull_mode = CanvasCullMode::CanvasCullModeNone;
3202
+ break;
3203
+ case 1:
3204
+ primitive->cull_mode = CanvasCullMode::CanvasCullModeFront;
3205
+ break;
3206
+ case 2:
3207
+ primitive->cull_mode = CanvasCullMode::CanvasCullModeBack;
3208
+ break;
3209
+ default:
3210
+ break;
3211
+ }
3212
+ } else if (cullModeValue->IsString()) {
3213
+
3214
+ auto cullMode = ConvertFromV8String(isolate, cullModeValue);
3215
+
3216
+ if (cullMode == "none") {
3217
+ primitive->cull_mode = CanvasCullMode::CanvasCullModeNone;
3218
+ } else if (cullMode == "front") {
3219
+ primitive->cull_mode = CanvasCullMode::CanvasCullModeFront;
3220
+ } else if (cullMode == "back") {
3221
+ primitive->cull_mode = CanvasCullMode::CanvasCullModeBack;
3222
+ }
3223
+ }
3224
+
3225
+ }
3226
+
3227
+ v8::Local<v8::Value> frontFaceValue;
3228
+
3229
+ if (primitiveObj->Get(context, ConvertToV8String(isolate, "frontFace")).ToLocal(
3230
+ &frontFaceValue)) {
3231
+ if (frontFaceValue->IsUint32()) {
3232
+ auto frontFace = frontFaceValue.As<v8::Uint32>()->Value();
3233
+ switch (frontFace) {
3234
+ case 0:
3235
+ primitive->front_face = CanvasFrontFace::CanvasFrontFaceCcw;
3236
+ break;
3237
+ case 1:
3238
+ primitive->front_face = CanvasFrontFace::CanvasFrontFaceCw;
3239
+ break;
3240
+ default:
3241
+ break;
3242
+ }
3243
+ } else if (frontFaceValue->IsString()) {
3244
+ auto frontFace = ConvertFromV8String(isolate, frontFaceValue);
3245
+ if (frontFace == "ccw") {
3246
+ primitive->front_face = CanvasFrontFace::CanvasFrontFaceCcw;
3247
+ } else if (frontFace == "cw") {
3248
+ primitive->front_face = CanvasFrontFace::CanvasFrontFaceCw;
3249
+ }
3250
+ }
3251
+ }
3252
+
3253
+
3254
+ v8::Local<v8::Value> stripIndexFormatValue;
3255
+
3256
+ if (primitiveObj->Get(context, ConvertToV8String(isolate, "stripIndexFormat")).ToLocal(
3257
+ &stripIndexFormatValue)) {
3258
+ if (stripIndexFormatValue->IsUint32()) {
3259
+ auto stripIndexFormat = stripIndexFormatValue.As<v8::Uint32>()->Value();
3260
+ switch (stripIndexFormat) {
3261
+ case 0:
3262
+ primitive->strip_index_format = CanvasOptionalIndexFormat{
3263
+ CanvasOptionalIndexFormatSome,
3264
+ CanvasIndexFormat::CanvasIndexFormatUint16
3265
+ };
3266
+ break;
3267
+ case 1:
3268
+ primitive->strip_index_format = CanvasOptionalIndexFormat{
3269
+ CanvasOptionalIndexFormatSome,
3270
+ CanvasIndexFormat::CanvasIndexFormatUint32
3271
+ };
3272
+ break;
3273
+ default:
3274
+ break;
3275
+ }
3276
+ } else if (stripIndexFormatValue->IsString()) {
3277
+ auto stripIndexFormat = ConvertFromV8String(isolate, stripIndexFormatValue);
3278
+
3279
+
3280
+ if (stripIndexFormat == "uint16") {
3281
+ primitive->strip_index_format = CanvasOptionalIndexFormat{
3282
+ CanvasOptionalIndexFormatSome,
3283
+ CanvasIndexFormat::CanvasIndexFormatUint16
3284
+ };
3285
+ } else if (stripIndexFormat == "uint32") {
3286
+ primitive->strip_index_format = CanvasOptionalIndexFormat{
3287
+ CanvasOptionalIndexFormatSome,
3288
+ CanvasIndexFormat::CanvasIndexFormatUint32
3289
+ };
3290
+ }
3291
+ }
3292
+ }
3293
+
3294
+
3295
+ v8::Local<v8::Value> topologyValue;
3296
+
3297
+ if (primitiveObj->Get(context, ConvertToV8String(isolate, "topology")).ToLocal(
3298
+ &topologyValue)) {
3299
+
3300
+ if (topologyValue->IsUint32()) {
3301
+ auto topology = topologyValue.As<v8::Uint32>()->Value();
3302
+ switch (topology) {
3303
+ case 0:
3304
+ primitive->topology = CanvasPrimitiveTopology::CanvasPrimitiveTopologyPointList;
3305
+ break;
3306
+ case 1:
3307
+ primitive->topology = CanvasPrimitiveTopology::CanvasPrimitiveTopologyLineList;
3308
+ break;
3309
+ case 2:
3310
+ primitive->topology = CanvasPrimitiveTopology::CanvasPrimitiveTopologyLineStrip;
3311
+ break;
3312
+ case 3:
3313
+ primitive->topology = CanvasPrimitiveTopology::CanvasPrimitiveTopologyTriangleList;
3314
+ break;
3315
+ case 4:
3316
+ primitive->topology = CanvasPrimitiveTopology::CanvasPrimitiveTopologyTriangleStrip;
3317
+ break;
3318
+ default:
3319
+ break;
3320
+ }
3321
+ } else if (topologyValue->IsString()) {
3322
+ auto topology = ConvertFromV8String(isolate, topologyValue);
3323
+ if (topology == "line-list") {
3324
+ primitive->topology = CanvasPrimitiveTopology::CanvasPrimitiveTopologyLineList;
3325
+ } else if (topology == "line-strip") {
3326
+ primitive->topology = CanvasPrimitiveTopology::CanvasPrimitiveTopologyLineStrip;
3327
+ } else if (topology == "point-list") {
3328
+ primitive->topology = CanvasPrimitiveTopology::CanvasPrimitiveTopologyPointList;
3329
+ } else if (topology == "triangle-list") {
3330
+ primitive->topology = CanvasPrimitiveTopology::CanvasPrimitiveTopologyTriangleList;
3331
+ } else if (topology == "triangle-strip") {
3332
+ primitive->topology = CanvasPrimitiveTopology::CanvasPrimitiveTopologyTriangleStrip;
3333
+ }
3334
+ }
3335
+
3336
+ }
3337
+
3338
+
3339
+ v8::Local<v8::Value> unclippedDepthValue;
3340
+ primitiveObj->Get(context, ConvertToV8String(isolate, "unclippedDepth")).ToLocal(
3341
+ &unclippedDepthValue);
3342
+
3343
+ if (!unclippedDepthValue.IsEmpty() && unclippedDepthValue->IsBoolean()) {
3344
+ primitive->unclipped_depth = unclippedDepthValue->BooleanValue(isolate);
3345
+ }
3346
+
3347
+ descriptor.primitive = primitive;
3348
+
3349
+ }
3350
+
3351
+
3352
+ v8::Local<v8::Value> vertexValue;
3353
+ options->Get(context, ConvertToV8String(isolate, "vertex")).ToLocal(
3354
+ &vertexValue);
3355
+
3356
+
3357
+ CanvasVertexState *vertex = nullptr;
3358
+
3359
+ std::vector<CanvasVertexBufferLayout> bufferLayout;
3360
+
3361
+ std::vector<std::vector<CanvasVertexAttribute>> attributes;
3362
+
3363
+ if (!vertexValue.IsEmpty() && vertexValue->IsObject()) {
3364
+ auto vertexObj = vertexValue.As<v8::Object>();
3365
+ vertex = new CanvasVertexState{};
3366
+
3367
+ v8::Local<v8::Value> moduleVal;
3368
+ vertexObj->Get(context, ConvertToV8String(isolate, "module")).ToLocal(&moduleVal);
3369
+
3370
+ auto module = GPUShaderModuleImpl::GetPointer(moduleVal.As<v8::Object>());
3371
+
3372
+ vertex->module = module->GetShaderModule();
3373
+
3374
+ v8::Local<v8::Value> constantsVal;
3375
+ vertexObj->Get(context, ConvertToV8String(isolate, "constants")).ToLocal(&constantsVal);
3376
+
3377
+ if (!constantsVal.IsEmpty() && constantsVal->IsMap()) {
3378
+ auto constants = constantsVal.As<v8::Map>();
3379
+ auto keyValues = constants->AsArray();
3380
+ auto len = keyValues->Length();
3381
+ CanvasConstants *store = nullptr;
3382
+
3383
+ if (len > 0) {
3384
+ store = canvas_native_webgpu_constants_create();
3385
+ for (int i = 0; i < len; i += 2) {
3386
+ auto k = i;
3387
+ auto v = k + 1;
3388
+
3389
+ v8::Local<v8::Value> keyVal;
3390
+ keyValues->Get(context, k).ToLocal(&keyVal);
3391
+ v8::Local<v8::Value> valueVal;
3392
+ keyValues->Get(context, v).ToLocal(&valueVal);
3393
+
3394
+
3395
+ if (!keyVal.IsEmpty() && keyVal->IsString() && !valueVal.IsEmpty() &&
3396
+ valueVal->IsNumber()) {
3397
+ canvas_native_webgpu_constants_insert(
3398
+ store,
3399
+ *v8::String::Utf8Value(isolate, keyVal),
3400
+ valueVal.As<v8::Number>()->Value()
3401
+ );
3402
+ }
3403
+
3404
+ }
3405
+ }
3406
+
3407
+ vertex->constants = store;
3408
+
3409
+ }
3410
+
3411
+ v8::Local<v8::Value> buffersVal;
3412
+ vertexObj->Get(context, ConvertToV8String(isolate, "buffers")).ToLocal(&buffersVal);
3413
+
3414
+ uint64_t stride = 0;
3415
+ if (!buffersVal.IsEmpty() && buffersVal->IsArray()) {
3416
+ auto buffers = buffersVal.As<v8::Array>();
3417
+ auto len = buffers->Length();
3418
+
3419
+ for (int i = 0; i < len; i++) {
3420
+ auto buffer = buffers->Get(context, i).ToLocalChecked().As<v8::Object>();
3421
+
3422
+ v8::Local<v8::Value> arrayStride;
3423
+
3424
+ buffer->Get(context, ConvertToV8String(isolate, "arrayStride")).ToLocal(
3425
+ &arrayStride);
3426
+
3427
+ if (!arrayStride.IsEmpty() && arrayStride->IsNumber()) {
3428
+ stride = (uint64_t) arrayStride.As<v8::Number>()->Value();
3429
+ }
3430
+
3431
+ std::vector<CanvasVertexAttribute> attributes_;
3432
+
3433
+ v8::Local<v8::Value> attributesValue;
3434
+
3435
+ buffer->Get(context, ConvertToV8String(isolate, "attributes")).ToLocal(
3436
+ &attributesValue);
3437
+
3438
+ if (!attributesValue.IsEmpty() && attributesValue->IsArray()) {
3439
+ auto attributes_array = attributesValue.As<v8::Array>();
3440
+ auto attributes_len = attributes_array->Length();
3441
+
3442
+ for (int j = 0; j < attributes_len; j++) {
3443
+ auto attr = attributes_array->Get(context,
3444
+ j).ToLocalChecked().As<v8::Object>();
3445
+ auto format = attr->Get(context, ConvertToV8String(isolate,
3446
+ "format")).ToLocalChecked()->Uint32Value(
3447
+ context).ToChecked();
3448
+
3449
+ auto offset = (uint64_t) attr->Get(context, ConvertToV8String(isolate,
3450
+ "offset")).ToLocalChecked()->NumberValue(
3451
+ context).ToChecked();
3452
+ auto shaderLocation = attr->Get(context, ConvertToV8String(isolate,
3453
+ "shaderLocation")).ToLocalChecked()->Uint32Value(
3454
+ context).ToChecked();
3455
+
3456
+ auto attribute = CanvasVertexAttribute{
3457
+ (CanvasVertexFormat) format,
3458
+ offset,
3459
+ shaderLocation
3460
+ };
3461
+
3462
+ attributes_.push_back(attribute);
3463
+ }
3464
+
3465
+ attributes.push_back(attributes_);
3466
+ }
3467
+
3468
+
3469
+ CanvasVertexStepMode stepMode = CanvasVertexStepModeVertex;
3470
+
3471
+ v8::Local<v8::Value> stepModeVal;
3472
+
3473
+ buffer->Get(context, ConvertToV8String(isolate, "stepMode")).ToLocal(
3474
+ &stepModeVal);
3475
+
3476
+
3477
+ if (!stepModeVal.IsEmpty()) {
3478
+ if (stepModeVal->IsUint32()) {
3479
+ switch (stepModeVal.As<v8::Uint32>()->Value()) {
3480
+ case 0:
3481
+ stepMode = CanvasVertexStepMode::CanvasVertexStepModeVertex;
3482
+ break;
3483
+ case 1:
3484
+ stepMode = CanvasVertexStepMode::CanvasVertexStepModeInstance;
3485
+ break;
3486
+ }
3487
+ } else if (stepModeVal->IsString()) {
3488
+ auto stepModeStr = ConvertFromV8String(isolate, stepModeVal);
3489
+ if (stepModeStr == "vertex") {
3490
+ stepMode = CanvasVertexStepMode::CanvasVertexStepModeVertex;
3491
+ } else if (stepModeStr == "instance") {
3492
+ stepMode = CanvasVertexStepMode::CanvasVertexStepModeInstance;
3493
+ }
3494
+ }
3495
+ }
3496
+
3497
+ auto vertexBufferLayout = CanvasVertexBufferLayout{
3498
+ stride,
3499
+ stepMode,
3500
+ attributes[i].data(),
3501
+ attributes[i].size()
3502
+ };
3503
+
3504
+ bufferLayout.push_back(vertexBufferLayout);
3505
+ }
3506
+
3507
+ vertex->buffers = bufferLayout.data();
3508
+ vertex->buffers_size = bufferLayout.size();
3509
+
3510
+ }
3511
+
3512
+
3513
+ v8::Local<v8::Value> entryPoint;
3514
+ vertexObj->Get(context, ConvertToV8String(isolate, "entryPoint")).ToLocal(&entryPoint);
3515
+
3516
+
3517
+ if (!entryPoint.IsEmpty() && entryPoint->IsString()) {
3518
+ auto ep = v8::String::Utf8Value(isolate, entryPoint);
3519
+ char *entry_point = (char *) malloc(ep.length());
3520
+ std::strcpy(entry_point, *ep);
3521
+ vertex->entry_point = entry_point;
3522
+ }
3523
+
3524
+ descriptor.vertex = vertex;
3525
+
3526
+ }
3527
+
3528
+ auto async_callback = new AsyncCallback(isolate, callback.As<v8::Function>(),
3529
+ [](bool success, void *data) {
3530
+ if (data != nullptr) {
3531
+ auto async_data = static_cast<AsyncCallback *>(data);
3532
+ auto func = async_data->inner_.get();
3533
+ if (func != nullptr &&
3534
+ func->isolate_ != nullptr) {
3535
+ v8::Isolate *isolate = func->isolate_;
3536
+ v8::Locker locker(isolate);
3537
+ v8::Isolate::Scope isolate_scope(
3538
+ isolate);
3539
+ v8::HandleScope handle_scope(isolate);
3540
+ v8::Local<v8::Function> callback = func->callback_.Get(
3541
+ isolate);
3542
+ v8::Local<v8::Context> context = callback->GetCreationContextChecked();
3543
+ v8::Context::Scope context_scope(
3544
+ context);
3545
+
3546
+ RenderPipeLineAsyncData *pipelineData = nullptr;
3547
+ if (func->data != nullptr) {
3548
+ pipelineData = static_cast<RenderPipeLineAsyncData *>(func->data);
3549
+ }
3550
+
3551
+ if (pipelineData == nullptr) {
3552
+ // Should never happen
3553
+ auto error = v8::Object::New(isolate);
3554
+ error->Set(context,
3555
+ ConvertToV8String(isolate,
3556
+ "error"),
3557
+ v8::Exception::Error(
3558
+ ConvertToV8String(
3559
+ isolate,
3560
+ "Internal Error")));
3561
+ error->Set(context, ConvertToV8String(
3562
+ isolate,
3563
+ "type"),
3564
+ v8::Uint32::NewFromUnsigned(
3565
+ isolate,
3566
+ (uint32_t) CanvasGPUErrorType::CanvasGPUErrorTypeInternal));
3567
+
3568
+ v8::Local<v8::Value> args[1] = {error};
3569
+
3570
+ callback->Call(context,
3571
+ context->Global(),
3572
+ 1,
3573
+ args); // ignore JS return value
3574
+ delete static_cast<AsyncCallback *>(data);
3575
+
3576
+ return;
3577
+ }
3578
+
3579
+ if (pipelineData->type !=
3580
+ CanvasGPUErrorType::CanvasGPUErrorTypeNone) {
3581
+
3582
+
3583
+ auto error = v8::Object::New(isolate);
3584
+ error->Set(context,
3585
+ ConvertToV8String(isolate,
3586
+ "error"),
3587
+ v8::Exception::Error(
3588
+ ConvertToV8String(
3589
+ isolate,
3590
+ pipelineData->errorMessage)));
3591
+ error->Set(context, ConvertToV8String(
3592
+ isolate,
3593
+ "type"),
3594
+ v8::Uint32::NewFromUnsigned(
3595
+ isolate,
3596
+ (uint32_t) pipelineData->type));
3597
+
3598
+ v8::Local<v8::Value> args[1] = {error};
3599
+
3600
+ callback->Call(context,
3601
+ context->Global(),
3602
+ 1,
3603
+ args); // ignore JS return value
3604
+ } else {
3605
+
3606
+ auto ret = GPURenderPipelineImpl::NewInstance(
3607
+ isolate,
3608
+ new GPURenderPipelineImpl(
3609
+ pipelineData->pipeline));
3610
+
3611
+ v8::Local<v8::Value> args[2] = {
3612
+ v8::Null(isolate), ret};
3613
+
3614
+
3615
+ callback->Call(context,
3616
+ context->Global(),
3617
+ 2,
3618
+ args); // ignore JS return value
3619
+ }
3620
+
3621
+ if (pipelineData != nullptr) {
3622
+ delete pipelineData;
3623
+ pipelineData = nullptr;
3624
+ }
3625
+
3626
+ delete static_cast<AsyncCallback *>(data);
3627
+ }
3628
+ }
3629
+ });
3630
+
3631
+ auto data = new RenderPipeLineAsyncData{
3632
+ nullptr,
3633
+ nullptr,
3634
+ nullptr,
3635
+ nullptr,
3636
+ CanvasGPUErrorType::CanvasGPUErrorTypeNone,
3637
+ nullptr,
3638
+ nullptr,
3639
+ nullptr,
3640
+ nullptr,
3641
+ nullptr,
3642
+ nullptr
3643
+ };
3644
+
3645
+ if (fragment != nullptr) {
3646
+ if (fragment->entry_point != nullptr) {
3647
+ data->fragment_entry_point = (char *) fragment->entry_point;
3648
+ }
3649
+ }
3650
+
3651
+ if (primitive != nullptr) {
3652
+ data->primitive = primitive;
3653
+ }
3654
+
3655
+ if (multisample != nullptr) {
3656
+ data->multisample = multisample;
3657
+ }
3658
+
3659
+ if (vertex != nullptr) {
3660
+ if (vertex->constants != nullptr) {
3661
+ data->vertex_constants = (CanvasConstants *) vertex->constants;
3662
+ }
3663
+
3664
+ if (vertex->entry_point != nullptr) {
3665
+ data->vertex_entry_point = (char *) descriptor.vertex->entry_point;
3666
+ }
3667
+
3668
+ }
3669
+
3670
+ if (stencil != nullptr) {
3671
+ delete descriptor.depth_stencil;
3672
+ data->depth_stencil = stencil;
3673
+ }
3674
+
3675
+ async_callback->inner_->data = data;
3676
+
3677
+ async_callback->prepare();
3678
+
3679
+ canvas_native_webgpu_device_create_render_pipeline_async(ptr->GetGPUDevice(),
3680
+ &descriptor, [](
3681
+ const struct CanvasGPURenderPipeline *pipeline,
3682
+ enum CanvasGPUErrorType type,
3683
+ char *message,
3684
+ void *data) {
3685
+ if (data != nullptr) {
3686
+ auto async_data = static_cast<AsyncCallback *>(data);
3687
+ auto inner = async_data->inner_.get();
3688
+ if (inner != nullptr) {
3689
+ auto pipeline_data = static_cast<RenderPipeLineAsyncData *>(inner->data);
3690
+ pipeline_data->errorMessage = message;
3691
+ pipeline_data->type = type;
3692
+ pipeline_data->pipeline = pipeline;
3693
+ async_data->execute(
3694
+ true);
3695
+ }
3696
+ }
3697
+ }, async_callback);
3698
+ }
3699
+
2305
3700
  void GPUDeviceImpl::CreateSampler(const v8::FunctionCallbackInfo<v8::Value> &args) {
2306
3701
  GPUDeviceImpl *ptr = GetPointer(args.This());
2307
3702
  if (ptr == nullptr) {
@@ -2453,7 +3848,7 @@ void GPUDeviceImpl::CreateSampler(const v8::FunctionCallbackInfo<v8::Value> &arg
2453
3848
  &maxAnisotropyVal);
2454
3849
 
2455
3850
  if (!maxAnisotropyVal.IsEmpty() && maxAnisotropyVal->IsNumber()) {
2456
- maxAnisotropy = (u_short) maxAnisotropyVal->NumberValue(context).FromJust();
3851
+ maxAnisotropy = (uint16_t) maxAnisotropyVal->NumberValue(context).FromJust();
2457
3852
  }
2458
3853
 
2459
3854