@qvac/ocr-ggml 0.24.2 → 0.25.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +21 -0
- package/index.d.ts +10 -0
- package/index.js +17 -0
- package/lib/main-gpu.d.ts +2 -0
- package/lib/main-gpu.js +5 -0
- package/package.json +9 -3
- package/prebuilds/android-arm64/qvac__ocr-ggml.bare +0 -0
- package/prebuilds/darwin-arm64/qvac__ocr-ggml.bare +0 -0
- package/prebuilds/darwin-arm64/qvac__ocr-ggml.bare.exports +2 -2
- package/prebuilds/darwin-x64/qvac__ocr-ggml.bare +0 -0
- package/prebuilds/darwin-x64/qvac__ocr-ggml.bare.exports +2 -2
- package/prebuilds/ios-arm64/qvac__ocr-ggml.bare +0 -0
- package/prebuilds/ios-arm64/qvac__ocr-ggml.bare.exports +2 -2
- package/prebuilds/ios-arm64-simulator/qvac__ocr-ggml.bare +0 -0
- package/prebuilds/ios-arm64-simulator/qvac__ocr-ggml.bare.exports +2 -2
- package/prebuilds/ios-x64-simulator/qvac__ocr-ggml.bare +0 -0
- package/prebuilds/ios-x64-simulator/qvac__ocr-ggml.bare.exports +2 -2
- package/prebuilds/linux-arm64/qvac__ocr-ggml.bare +0 -0
- package/prebuilds/linux-x64/qvac__ocr-ggml.bare +0 -0
- package/prebuilds/win32-x64/qvac__ocr-ggml.bare +0 -0
- package/prebuilds/win32-x64/qvac__ocr-ggml.bare.exports +0 -0
- package/test/integration/backend-device.test.js +97 -0
package/README.md
CHANGED
|
@@ -149,6 +149,7 @@ bare examples/backend-device.js --backend metal
|
|
|
149
149
|
| `params.nThreads` | `number` | | `0` (auto) | CPU thread count for GGML; `<0` leaves the GGML default |
|
|
150
150
|
| `params.backendsDir` | `string` | | `<package>/prebuilds` | directory holding `libggml-*.so` backend shared libs |
|
|
151
151
|
| `params.backendDevice` | `'cpu'` \| `'vulkan'` \| `'metal'` \| `'opencl'` | | `'cpu'` | ggml backend device. `'vulkan'` (Linux/Windows/Android), `'metal'` (Apple) and `'opencl'` (Android/Adreno) opt in to GPU inference with transparent CPU fallback — see [Backend device](#backend-device-cpu--vulkan--metal--opencl) |
|
|
152
|
+
| `params.main-gpu` / `params.main_gpu` | `number` \| `string` | | _prefer dedicated_ | Raw ggml registry index or strict GPU class; requires GPU `backendDevice`. See below. |
|
|
152
153
|
| `params.gpuDevice` | `number` | | _prefer discrete_ | 0-based index into the matching GPU/iGPU devices for `'vulkan'`/`'metal'`/`'opencl'`; out-of-range → CPU fallback — see [Selecting a specific GPU](#selecting-a-specific-gpu-gpudevice) |
|
|
153
154
|
| `opts.stats` | `boolean` | | `false` | emit timing stats on `finish` |
|
|
154
155
|
| `logger` | `Object` | | `null` | optional `{ info, warn, error, debug }` — receives C++ log lines |
|
|
@@ -278,6 +279,26 @@ Behaviour and expectations:
|
|
|
278
279
|
with identical output. Other GPUs (Adreno OpenCL, Apple Metal, NVIDIA/Intel
|
|
279
280
|
Vulkan) keep full-GPU detection.
|
|
280
281
|
|
|
282
|
+
### Shared GPU selection (`main-gpu`)
|
|
283
|
+
|
|
284
|
+
With a GPU `backendDevice`, set `'main-gpu': N` (or `main_gpu: N`) to select
|
|
285
|
+
that **raw ggml registry index before backend filtering**. For example, with
|
|
286
|
+
`[ROCm0, Vulkan0]`, `'main-gpu': 0` and `backendDevice: 'vulkan'` falls back to
|
|
287
|
+
CPU; it never renumbers Vulkan0 to index 0. An in-range CPU, unsupported,
|
|
288
|
+
or safety-excluded target also falls back to CPU. An out-of-range integer
|
|
289
|
+
(including negative values) emits a warning and uses normal selection.
|
|
290
|
+
|
|
291
|
+
`'dedicated'` selects only a dedicated GPU; `'integrated'` selects only an
|
|
292
|
+
integrated GPU. If that class is unavailable, selection falls back to CPU.
|
|
293
|
+
Without a selector, GPU selection prefers dedicated devices. Adreno Vulkan
|
|
294
|
+
and required OCR-op safety checks apply to all `main-gpu` requests.
|
|
295
|
+
`backendDevice: 'cpu'` (the default) remains CPU, regardless of this selector.
|
|
296
|
+
|
|
297
|
+
Use only one of `main-gpu`, `main_gpu`, or legacy `gpuDevice`. The new selector
|
|
298
|
+
accepts signed 32-bit integer numbers or integer strings, and case-insensitive
|
|
299
|
+
class strings. Null, booleans, fractions, overflow, and other strings are rejected.
|
|
300
|
+
`gpuDevice` retains its existing index into the filtered backend list.
|
|
301
|
+
|
|
281
302
|
### Selecting a specific GPU (`gpuDevice`)
|
|
282
303
|
|
|
283
304
|
On a host with more than one GPU (e.g. a discrete GPU plus an integrated GPU,
|
package/index.d.ts
CHANGED
|
@@ -97,6 +97,16 @@ export interface OcrGgmlParams {
|
|
|
97
97
|
* the README).
|
|
98
98
|
*/
|
|
99
99
|
gpuDevice?: number;
|
|
100
|
+
/**
|
|
101
|
+
* Raw ggml registry index (integer number/string), or a GPU class (case-insensitive).
|
|
102
|
+
* An unavailable/excluded in-range device or absent class falls back to CPU.
|
|
103
|
+
* Out-of-range indices warn and use the default dedicated-first selection.
|
|
104
|
+
* Requires a GPU backendDevice; CPU remains the default. Cannot be combined
|
|
105
|
+
* with gpuDevice or main_gpu. Adreno Vulkan safety checks still apply.
|
|
106
|
+
*/
|
|
107
|
+
"main-gpu"?: number | string;
|
|
108
|
+
/** Alias for main-gpu; provide only one spelling. */
|
|
109
|
+
main_gpu?: number | string;
|
|
100
110
|
}
|
|
101
111
|
export type { BackendInfo, OcrGgmlRunOptions };
|
|
102
112
|
export interface OcrGgmlArgs {
|
package/index.js
CHANGED
|
@@ -11,6 +11,7 @@ const ocr_ggml_1 = require("./ocr-ggml");
|
|
|
11
11
|
const error_1 = require("./lib/error");
|
|
12
12
|
Object.defineProperty(exports, "QvacErrorAddonOcrGgml", { enumerable: true, get: function () { return error_1.QvacErrorAddonOcrGgml; } });
|
|
13
13
|
Object.defineProperty(exports, "ERR_CODES", { enumerable: true, get: function () { return error_1.ERR_CODES; } });
|
|
14
|
+
const main_gpu_1 = require("./lib/main-gpu");
|
|
14
15
|
const DOCTR_INTERNAL_LANG_LIST = ["en"];
|
|
15
16
|
/**
|
|
16
17
|
* Native language-validation failure messages (see the EasyOCR pipeline's
|
|
@@ -139,6 +140,20 @@ class OcrGgml {
|
|
|
139
140
|
adds: "langList (non-empty array)",
|
|
140
141
|
});
|
|
141
142
|
}
|
|
143
|
+
const selectors = ["main-gpu", "main_gpu", "gpuDevice"];
|
|
144
|
+
if (selectors.filter((key) => this.params[key] !== undefined).length > 1) {
|
|
145
|
+
throw new TypeError("Use only one of main-gpu, main_gpu, or gpuDevice");
|
|
146
|
+
}
|
|
147
|
+
const rawMainGpu = this.params["main-gpu"] !== undefined
|
|
148
|
+
? this.params["main-gpu"] : this.params.main_gpu;
|
|
149
|
+
const mainGpu = typeof rawMainGpu === "string"
|
|
150
|
+
? (/^[+-]?\d+$/.test(rawMainGpu) ? Number(rawMainGpu) : rawMainGpu.toLowerCase())
|
|
151
|
+
: rawMainGpu;
|
|
152
|
+
if (mainGpu !== undefined && mainGpu !== "dedicated" && mainGpu !== "integrated" &&
|
|
153
|
+
!(typeof mainGpu === "number" && Number.isInteger(mainGpu) &&
|
|
154
|
+
mainGpu >= main_gpu_1.MIN_MAIN_GPU_INDEX && mainGpu <= main_gpu_1.MAX_MAIN_GPU_INDEX)) {
|
|
155
|
+
throw new TypeError("main-gpu must be a 32-bit integer registry index, 'dedicated', or 'integrated'");
|
|
156
|
+
}
|
|
142
157
|
const configurationParams = {
|
|
143
158
|
pathDetector: this.params.pathDetector,
|
|
144
159
|
pathRecognizer: this.params.pathRecognizer,
|
|
@@ -157,6 +172,8 @@ class OcrGgml {
|
|
|
157
172
|
"pipelineType",
|
|
158
173
|
"backendDevice",
|
|
159
174
|
"gpuDevice",
|
|
175
|
+
"main-gpu",
|
|
176
|
+
"main_gpu",
|
|
160
177
|
];
|
|
161
178
|
for (const field of optionalFields) {
|
|
162
179
|
if (this.params[field] !== undefined) {
|
package/lib/main-gpu.js
ADDED
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@qvac/ocr-ggml",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.25.0",
|
|
4
4
|
"description": "GGML-backed OCR addon for qvac (EasyOCR and DocTR pipelines on GGUF weights)",
|
|
5
5
|
"addon": true,
|
|
6
6
|
"engines": {
|
|
@@ -95,7 +95,7 @@
|
|
|
95
95
|
},
|
|
96
96
|
"dependencies": {
|
|
97
97
|
"@qvac/error": "^0.1.0",
|
|
98
|
-
"@qvac/fabric": "^0.
|
|
98
|
+
"@qvac/fabric": "^0.17.0",
|
|
99
99
|
"@qvac/infer-base": "^0.6.2",
|
|
100
100
|
"@qvac/logging": "^0.1.0",
|
|
101
101
|
"bare-fetch": "^3.0.1",
|
|
@@ -116,7 +116,13 @@
|
|
|
116
116
|
"types": "./addonLogging.d.ts",
|
|
117
117
|
"default": "./addonLogging.js"
|
|
118
118
|
},
|
|
119
|
-
"./addonLogging.js": "./addonLogging.js"
|
|
119
|
+
"./addonLogging.js": "./addonLogging.js",
|
|
120
|
+
"./lib/main-gpu": {
|
|
121
|
+
"types": "./lib/main-gpu.d.ts",
|
|
122
|
+
"default": "./lib/main-gpu.js"
|
|
123
|
+
},
|
|
124
|
+
"./binding": "./binding.js",
|
|
125
|
+
"./binding.js": "./binding.js"
|
|
120
126
|
},
|
|
121
127
|
"types": "index.d.ts"
|
|
122
128
|
}
|
|
Binary file
|
|
Binary file
|
|
@@ -7,7 +7,7 @@
|
|
|
7
7
|
],
|
|
8
8
|
"current_versions": [
|
|
9
9
|
{
|
|
10
|
-
"version": "0.
|
|
10
|
+
"version": "0.25"
|
|
11
11
|
}
|
|
12
12
|
],
|
|
13
13
|
"exported_symbols": [
|
|
@@ -2543,7 +2543,6 @@
|
|
|
2543
2543
|
"_png_write_bKGD",
|
|
2544
2544
|
"_png_set_hIST",
|
|
2545
2545
|
"__ZN2cv3MatC2ENS_5Size_IiEEi",
|
|
2546
|
-
"__ZN23qvac_lib_infer_ocr_ggml21ocr_backend_selection19selectBackendDeviceENS_13BackendDeviceENSt3__18optionalIiEE",
|
|
2547
2546
|
"__ZN2cv15ImageCollection4Impl3endEPS0_",
|
|
2548
2547
|
"_png_get_copyright",
|
|
2549
2548
|
"__Z6cvCeilRKN2cv9softfloatE",
|
|
@@ -2628,6 +2627,7 @@
|
|
|
2628
2627
|
"__ZN2cv15ImageCollection8iteratorppEi",
|
|
2629
2628
|
"_cvGetReal1D",
|
|
2630
2629
|
"__ZN2cv3MatC1Ev",
|
|
2630
|
+
"__ZN23qvac_lib_infer_ocr_ggml21ocr_backend_selection19selectBackendDeviceENS_13BackendDeviceENSt3__18optionalIiEENS3_INS2_7variantIJiNS_12MainGpuClassEEEEEE",
|
|
2631
2631
|
"_png_check_fp_string",
|
|
2632
2632
|
"__ZN2cv11linearPolarERKNS_11_InputArrayERKNS_12_OutputArrayENS_6Point_IfEEdi",
|
|
2633
2633
|
"__ZN2cv3LDAC1ERKNS_11_InputArrayES3_i",
|
|
Binary file
|
|
@@ -7,7 +7,7 @@
|
|
|
7
7
|
],
|
|
8
8
|
"current_versions": [
|
|
9
9
|
{
|
|
10
|
-
"version": "0.
|
|
10
|
+
"version": "0.25"
|
|
11
11
|
}
|
|
12
12
|
],
|
|
13
13
|
"exported_symbols": [
|
|
@@ -2597,7 +2597,6 @@
|
|
|
2597
2597
|
"_png_write_bKGD",
|
|
2598
2598
|
"_png_set_hIST",
|
|
2599
2599
|
"__ZN2cv3MatC2ENS_5Size_IiEEi",
|
|
2600
|
-
"__ZN23qvac_lib_infer_ocr_ggml21ocr_backend_selection19selectBackendDeviceENS_13BackendDeviceENSt3__18optionalIiEE",
|
|
2601
2600
|
"__ZN2cv15ImageCollection4Impl3endEPS0_",
|
|
2602
2601
|
"_png_get_copyright",
|
|
2603
2602
|
"__Z6cvCeilRKN2cv9softfloatE",
|
|
@@ -2680,6 +2679,7 @@
|
|
|
2680
2679
|
"__ZN2cv15ImageCollection8iteratorppEi",
|
|
2681
2680
|
"_cvGetReal1D",
|
|
2682
2681
|
"__ZN2cv3MatC1Ev",
|
|
2682
|
+
"__ZN23qvac_lib_infer_ocr_ggml21ocr_backend_selection19selectBackendDeviceENS_13BackendDeviceENSt3__18optionalIiEENS3_INS2_7variantIJiNS_12MainGpuClassEEEEEE",
|
|
2683
2683
|
"_png_check_fp_string",
|
|
2684
2684
|
"__ZN2cv11linearPolarERKNS_11_InputArrayERKNS_12_OutputArrayENS_6Point_IfEEdi",
|
|
2685
2685
|
"__ZN2cv3LDAC1ERKNS_11_InputArrayES3_i",
|
|
Binary file
|
|
@@ -7,7 +7,7 @@
|
|
|
7
7
|
],
|
|
8
8
|
"current_versions": [
|
|
9
9
|
{
|
|
10
|
-
"version": "0.
|
|
10
|
+
"version": "0.25"
|
|
11
11
|
}
|
|
12
12
|
],
|
|
13
13
|
"exported_symbols": [
|
|
@@ -2533,7 +2533,6 @@
|
|
|
2533
2533
|
"_png_write_bKGD",
|
|
2534
2534
|
"_png_set_hIST",
|
|
2535
2535
|
"__ZN2cv3MatC2ENS_5Size_IiEEi",
|
|
2536
|
-
"__ZN23qvac_lib_infer_ocr_ggml21ocr_backend_selection19selectBackendDeviceENS_13BackendDeviceENSt3__18optionalIiEE",
|
|
2537
2536
|
"__ZN2cv15ImageCollection4Impl3endEPS0_",
|
|
2538
2537
|
"_png_get_copyright",
|
|
2539
2538
|
"__Z6cvCeilRKN2cv9softfloatE",
|
|
@@ -2618,6 +2617,7 @@
|
|
|
2618
2617
|
"__ZN2cv15ImageCollection8iteratorppEi",
|
|
2619
2618
|
"_cvGetReal1D",
|
|
2620
2619
|
"__ZN2cv3MatC1Ev",
|
|
2620
|
+
"__ZN23qvac_lib_infer_ocr_ggml21ocr_backend_selection19selectBackendDeviceENS_13BackendDeviceENSt3__18optionalIiEENS3_INS2_7variantIJiNS_12MainGpuClassEEEEEE",
|
|
2621
2621
|
"_png_check_fp_string",
|
|
2622
2622
|
"__ZN2cv11linearPolarERKNS_11_InputArrayERKNS_12_OutputArrayENS_6Point_IfEEdi",
|
|
2623
2623
|
"__ZN2cv3LDAC1ERKNS_11_InputArrayES3_i",
|
|
Binary file
|
|
@@ -7,7 +7,7 @@
|
|
|
7
7
|
],
|
|
8
8
|
"current_versions": [
|
|
9
9
|
{
|
|
10
|
-
"version": "0.
|
|
10
|
+
"version": "0.25"
|
|
11
11
|
}
|
|
12
12
|
],
|
|
13
13
|
"exported_symbols": [
|
|
@@ -2533,7 +2533,6 @@
|
|
|
2533
2533
|
"_png_write_bKGD",
|
|
2534
2534
|
"_png_set_hIST",
|
|
2535
2535
|
"__ZN2cv3MatC2ENS_5Size_IiEEi",
|
|
2536
|
-
"__ZN23qvac_lib_infer_ocr_ggml21ocr_backend_selection19selectBackendDeviceENS_13BackendDeviceENSt3__18optionalIiEE",
|
|
2537
2536
|
"__ZN2cv15ImageCollection4Impl3endEPS0_",
|
|
2538
2537
|
"_png_get_copyright",
|
|
2539
2538
|
"__Z6cvCeilRKN2cv9softfloatE",
|
|
@@ -2618,6 +2617,7 @@
|
|
|
2618
2617
|
"__ZN2cv15ImageCollection8iteratorppEi",
|
|
2619
2618
|
"_cvGetReal1D",
|
|
2620
2619
|
"__ZN2cv3MatC1Ev",
|
|
2620
|
+
"__ZN23qvac_lib_infer_ocr_ggml21ocr_backend_selection19selectBackendDeviceENS_13BackendDeviceENSt3__18optionalIiEENS3_INS2_7variantIJiNS_12MainGpuClassEEEEEE",
|
|
2621
2621
|
"_png_check_fp_string",
|
|
2622
2622
|
"__ZN2cv11linearPolarERKNS_11_InputArrayERKNS_12_OutputArrayENS_6Point_IfEEdi",
|
|
2623
2623
|
"__ZN2cv3LDAC1ERKNS_11_InputArrayES3_i",
|
|
Binary file
|
|
@@ -7,7 +7,7 @@
|
|
|
7
7
|
],
|
|
8
8
|
"current_versions": [
|
|
9
9
|
{
|
|
10
|
-
"version": "0.
|
|
10
|
+
"version": "0.25"
|
|
11
11
|
}
|
|
12
12
|
],
|
|
13
13
|
"exported_symbols": [
|
|
@@ -2592,7 +2592,6 @@
|
|
|
2592
2592
|
"_png_write_bKGD",
|
|
2593
2593
|
"_png_set_hIST",
|
|
2594
2594
|
"__ZN2cv3MatC2ENS_5Size_IiEEi",
|
|
2595
|
-
"__ZN23qvac_lib_infer_ocr_ggml21ocr_backend_selection19selectBackendDeviceENS_13BackendDeviceENSt3__18optionalIiEE",
|
|
2596
2595
|
"__ZN2cv15ImageCollection4Impl3endEPS0_",
|
|
2597
2596
|
"_png_get_copyright",
|
|
2598
2597
|
"__Z6cvCeilRKN2cv9softfloatE",
|
|
@@ -2674,6 +2673,7 @@
|
|
|
2674
2673
|
"__ZN2cv15ImageCollection8iteratorppEi",
|
|
2675
2674
|
"_cvGetReal1D",
|
|
2676
2675
|
"__ZN2cv3MatC1Ev",
|
|
2676
|
+
"__ZN23qvac_lib_infer_ocr_ggml21ocr_backend_selection19selectBackendDeviceENS_13BackendDeviceENSt3__18optionalIiEENS3_INS2_7variantIJiNS_12MainGpuClassEEEEEE",
|
|
2677
2677
|
"_png_check_fp_string",
|
|
2678
2678
|
"__ZN2cv11linearPolarERKNS_11_InputArrayERKNS_12_OutputArrayENS_6Point_IfEEdi",
|
|
2679
2679
|
"__ZN2cv3LDAC1ERKNS_11_InputArrayES3_i",
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
@@ -2,6 +2,8 @@
|
|
|
2
2
|
|
|
3
3
|
const { OcrGgml } = require('../..')
|
|
4
4
|
const test = require('brittle')
|
|
5
|
+
const path = require('bare-path')
|
|
6
|
+
const { MIN_MAIN_GPU_INDEX, MAX_MAIN_GPU_INDEX } = require('@qvac/ocr-ggml/lib/main-gpu')
|
|
5
7
|
const {
|
|
6
8
|
isMobile,
|
|
7
9
|
platform,
|
|
@@ -33,6 +35,101 @@ const vulkanBackendLib = findVulkanBackendLib(PREBUILDS_DIR)
|
|
|
33
35
|
// host that did not ship a Vulkan backend lib.
|
|
34
36
|
const shouldSkip = isMobile || !vulkanBackendLib
|
|
35
37
|
|
|
38
|
+
function nativeBackendsDir() {
|
|
39
|
+
if (isMobile) return PREBUILDS_DIR
|
|
40
|
+
return path.join(path.dirname(require.resolve('@qvac/fabric/package')), 'prebuilds')
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
for (const key of ['main-gpu', 'main_gpu']) {
|
|
44
|
+
for (const value of [0, '+0', 'DEDICATED', 'Integrated']) {
|
|
45
|
+
test(
|
|
46
|
+
`native createInstance: ${key}=${value} resolves the requested device`,
|
|
47
|
+
{ timeout: TEST_TIMEOUT },
|
|
48
|
+
async function (t) {
|
|
49
|
+
const binding = require('../../binding')
|
|
50
|
+
const pathDetector = await ensureModelPath('detector_craft')
|
|
51
|
+
const pathRecognizer = await ensureModelPath('recognizer_latin')
|
|
52
|
+
const backendDevice = platform === 'darwin' || platform === 'ios' ? 'metal' : 'vulkan'
|
|
53
|
+
const handle = binding.createInstance(
|
|
54
|
+
{},
|
|
55
|
+
{
|
|
56
|
+
pathDetector,
|
|
57
|
+
pathRecognizer,
|
|
58
|
+
langList: ['en'],
|
|
59
|
+
backendDevice,
|
|
60
|
+
backendsDir: nativeBackendsDir(),
|
|
61
|
+
[key]: value
|
|
62
|
+
},
|
|
63
|
+
() => {}
|
|
64
|
+
)
|
|
65
|
+
try {
|
|
66
|
+
const info = binding.getBackendInfo(handle)
|
|
67
|
+
t.is(info.requested, backendDevice, 'native backend request is preserved')
|
|
68
|
+
const numeric = value === 0 || value === '+0'
|
|
69
|
+
if (info.backendDevice === 'CPU') {
|
|
70
|
+
t.is(info.deviceIndex, -1, 'fallback selects CPU')
|
|
71
|
+
const selectorReason = numeric
|
|
72
|
+
? 'main-gpu registry index 0 is not an eligible'
|
|
73
|
+
: 'main-gpu requested GPU class is unavailable'
|
|
74
|
+
t.ok(
|
|
75
|
+
info.fallbackReason.includes(selectorReason) ||
|
|
76
|
+
info.fallbackReason.includes('does not implement the OCR vision ops'),
|
|
77
|
+
'fallback identifies the parsed selector or the OCR safety check'
|
|
78
|
+
)
|
|
79
|
+
} else {
|
|
80
|
+
t.is(info.fallbackReason, '', 'selected GPU needs no fallback')
|
|
81
|
+
t.ok(info.deviceIndex >= 0, 'selected GPU has a registry index')
|
|
82
|
+
t.ok(
|
|
83
|
+
backendDevice === 'metal'
|
|
84
|
+
? /metal|mtl/i.test(info.backendName)
|
|
85
|
+
: /vulkan/i.test(info.backendName),
|
|
86
|
+
'resolved device belongs to the requested backend'
|
|
87
|
+
)
|
|
88
|
+
if (numeric) {
|
|
89
|
+
t.is(info.deviceIndex, 0, 'numeric selector preserves raw registry identity')
|
|
90
|
+
} else {
|
|
91
|
+
t.is(
|
|
92
|
+
info.backendDevice,
|
|
93
|
+
value.toLowerCase() === 'integrated' ? 'IGPU' : 'GPU',
|
|
94
|
+
'class selector is parsed case-insensitively and applied strictly'
|
|
95
|
+
)
|
|
96
|
+
}
|
|
97
|
+
}
|
|
98
|
+
} finally {
|
|
99
|
+
binding.destroyInstance(handle)
|
|
100
|
+
}
|
|
101
|
+
}
|
|
102
|
+
)
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
test(`native createInstance: ${key} rejects invalid indices before model loading`, (t) => {
|
|
106
|
+
const binding = require('../../binding')
|
|
107
|
+
for (const value of [
|
|
108
|
+
0.5,
|
|
109
|
+
NaN,
|
|
110
|
+
Infinity,
|
|
111
|
+
MAX_MAIN_GPU_INDEX + 1,
|
|
112
|
+
MIN_MAIN_GPU_INDEX - 1,
|
|
113
|
+
String(MAX_MAIN_GPU_INDEX + 1),
|
|
114
|
+
String(MIN_MAIN_GPU_INDEX - 1),
|
|
115
|
+
'+-1',
|
|
116
|
+
'1junk',
|
|
117
|
+
' 1'
|
|
118
|
+
]) {
|
|
119
|
+
t.exception(
|
|
120
|
+
() =>
|
|
121
|
+
binding.createInstance(
|
|
122
|
+
{},
|
|
123
|
+
{ pathDetector: 'unused', pathRecognizer: 'unused', langList: ['en'], [key]: value },
|
|
124
|
+
() => {}
|
|
125
|
+
),
|
|
126
|
+
/main-gpu must be a 32-bit integer registry index/,
|
|
127
|
+
`${key}=${value} is rejected by native validation`
|
|
128
|
+
)
|
|
129
|
+
}
|
|
130
|
+
})
|
|
131
|
+
}
|
|
132
|
+
|
|
36
133
|
test(
|
|
37
134
|
'backendDevice vulkan: selects Vulkan or reports an explicit CPU fallback',
|
|
38
135
|
{ timeout: TEST_TIMEOUT, skip: shouldSkip },
|