react-native-wgpu 0.1.13 → 0.1.14
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/android/CMakeLists.txt +7 -0
- package/android/build.gradle +4 -4
- package/android/cpp/cpp-adapter.cpp +10 -4
- package/android/cpp/platform/ThreadUtils.cpp +41 -0
- package/apple/platform/ThreadUtils.cpp +33 -0
- package/cpp/jsi/RNFJSIConverter.h +47 -28
- package/cpp/platform/ThreadUtils.h +30 -0
- package/cpp/rnwgpu/RNWebGPUManager.cpp +8 -0
- package/cpp/rnwgpu/api/Convertors.h +13 -5
- package/cpp/rnwgpu/api/GPU.cpp +4 -4
- package/cpp/rnwgpu/api/GPUAdapter.cpp +15 -14
- package/cpp/rnwgpu/api/GPUAdapterInfo.h +25 -4
- package/cpp/rnwgpu/api/GPUCanvasContext.cpp +3 -2
- package/cpp/rnwgpu/api/GPUDevice.cpp +5 -5
- package/cpp/rnwgpu/api/GPUDevice.h +7 -1
- package/cpp/rnwgpu/api/GPUFeatures.h +4 -4
- package/cpp/rnwgpu/api/GPUShaderModule.cpp +2 -1
- package/cpp/rnwgpu/api/descriptors/GPUCanvasConfiguration.h +3 -1
- package/cpp/threading/CallInvokerDispatcher.h +37 -0
- package/cpp/threading/Dispatcher.cpp +54 -0
- package/cpp/threading/Dispatcher.h +93 -0
- package/cpp/threading/ThreadPool.cpp +86 -0
- package/cpp/threading/ThreadPool.h +53 -0
- package/cpp/webgpu/webgpu.h +762 -758
- package/cpp/webgpu/webgpu_cpp.h +1827 -1626
- package/cpp/webgpu/webgpu_cpp_chained_struct.h +2 -0
- package/lib/commonjs/hooks.js +4 -2
- package/lib/commonjs/hooks.js.map +1 -1
- package/lib/module/hooks.js +4 -2
- package/lib/module/hooks.js.map +1 -1
- package/lib/typescript/lib/commonjs/hooks.d.ts.map +1 -1
- package/lib/typescript/lib/module/hooks.d.ts.map +1 -1
- package/lib/typescript/src/hooks.d.ts.map +1 -1
- package/libs/android/arm64-v8a/libwebgpu_dawn.so +0 -0
- package/libs/android/armeabi-v7a/libwebgpu_dawn.so +0 -0
- package/libs/android/x86/libwebgpu_dawn.so +0 -0
- package/libs/android/x86_64/libwebgpu_dawn.so +0 -0
- package/libs/apple/arm64_iphoneos/libwebgpu_dawn.a +0 -0
- package/libs/apple/arm64_iphonesimulator/libwebgpu_dawn.a +0 -0
- package/libs/apple/arm64_xros/libwebgpu_dawn.a +0 -0
- package/libs/apple/arm64_xrsimulator/libwebgpu_dawn.a +0 -0
- package/libs/apple/iphonesimulator/libwebgpu_dawn.a +0 -0
- package/libs/apple/libwebgpu_dawn.xcframework/Info.plist +10 -10
- package/libs/apple/libwebgpu_dawn.xcframework/ios-arm64/libwebgpu_dawn.a +0 -0
- package/libs/apple/libwebgpu_dawn.xcframework/ios-arm64_x86_64-simulator/libwebgpu_dawn.a +0 -0
- package/libs/apple/libwebgpu_dawn.xcframework/macos-arm64_x86_64/libwebgpu_dawn.a +0 -0
- package/libs/apple/libwebgpu_dawn.xcframework/xros-arm64/libwebgpu_dawn.a +0 -0
- package/libs/apple/libwebgpu_dawn.xcframework/xros-arm64-simulator/libwebgpu_dawn.a +0 -0
- package/libs/apple/universal_macosx/libwebgpu_dawn.a +0 -0
- package/libs/apple/x86_64_iphonesimulator/libwebgpu_dawn.a +0 -0
- package/libs/dawn.json +270 -251
- package/package.json +1 -1
- package/src/__tests__/Device.spec.ts +31 -0
- package/src/hooks.tsx +3 -2
package/android/CMakeLists.txt
CHANGED
|
@@ -25,6 +25,7 @@ find_package(fbjni REQUIRED CONFIG)
|
|
|
25
25
|
|
|
26
26
|
add_library(${PACKAGE_NAME} SHARED
|
|
27
27
|
./cpp/cpp-adapter.cpp
|
|
28
|
+
./cpp/platform/ThreadUtils.cpp
|
|
28
29
|
../cpp/rnwgpu/api/GPU.cpp
|
|
29
30
|
../cpp/rnwgpu/api/GPUAdapter.cpp
|
|
30
31
|
../cpp/rnwgpu/api/GPUSupportedLimits.cpp
|
|
@@ -48,6 +49,8 @@ add_library(${PACKAGE_NAME} SHARED
|
|
|
48
49
|
../cpp/jsi/RNFHybridObject.cpp
|
|
49
50
|
../cpp/jsi/RNFRuntimeCache.cpp
|
|
50
51
|
../cpp/jsi/RNFWorkletRuntimeRegistry.cpp
|
|
52
|
+
../cpp/threading/Dispatcher.cpp
|
|
53
|
+
../cpp/threading/ThreadPool.cpp
|
|
51
54
|
)
|
|
52
55
|
|
|
53
56
|
target_include_directories(
|
|
@@ -61,6 +64,7 @@ target_include_directories(
|
|
|
61
64
|
"${NODE_MODULES_DIR}/react-native/ReactCommon/runtimeexecutor"
|
|
62
65
|
"${NODE_MODULES_DIR}/react-native/ReactAndroid/src/main/jni"
|
|
63
66
|
"${NODE_MODULES_DIR}/react-native/ReactAndroid/src/main/java/com/facebook/react/turbomodule/core/jni"
|
|
67
|
+
"${NODE_MODULES_DIR}/react-native/ReactAndroid/src/main/jni/react/turbomodule"
|
|
64
68
|
|
|
65
69
|
../cpp
|
|
66
70
|
../cpp/rnwgpu
|
|
@@ -68,6 +72,8 @@ target_include_directories(
|
|
|
68
72
|
../cpp/rnwgpu/api/descriptors
|
|
69
73
|
../cpp/jsi
|
|
70
74
|
../cpp/webgpu
|
|
75
|
+
../cpp/threading
|
|
76
|
+
../cpp/platform
|
|
71
77
|
|
|
72
78
|
${libfbjni_include_DIRS}
|
|
73
79
|
)
|
|
@@ -84,5 +90,6 @@ target_link_libraries(
|
|
|
84
90
|
android
|
|
85
91
|
fbjni::fbjni
|
|
86
92
|
ReactAndroid::jsi
|
|
93
|
+
ReactAndroid::reactnativejni
|
|
87
94
|
webgpu_dawn
|
|
88
95
|
)
|
package/android/build.gradle
CHANGED
|
@@ -87,10 +87,10 @@ android {
|
|
|
87
87
|
}
|
|
88
88
|
|
|
89
89
|
packagingOptions {
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
90
|
+
excludes = [
|
|
91
|
+
"**/libjsi.so",
|
|
92
|
+
"**/libreactnativejni.so",
|
|
93
|
+
]
|
|
94
94
|
}
|
|
95
95
|
|
|
96
96
|
buildFeatures {
|
|
@@ -5,6 +5,7 @@
|
|
|
5
5
|
#include <jni.h>
|
|
6
6
|
#include <jsi/jsi.h>
|
|
7
7
|
|
|
8
|
+
#include <ReactCommon/CallInvokerHolder.h>
|
|
8
9
|
#include <android/native_window_jni.h>
|
|
9
10
|
#include <webgpu/webgpu_cpp.h>
|
|
10
11
|
|
|
@@ -17,13 +18,18 @@
|
|
|
17
18
|
std::shared_ptr<rnwgpu::RNWebGPUManager> manager;
|
|
18
19
|
|
|
19
20
|
extern "C" JNIEXPORT void JNICALL Java_com_webgpu_WebGPUModule_initializeNative(
|
|
20
|
-
JNIEnv *env, jobject /* this */, jlong jsRuntime,
|
|
21
|
-
jobject blobModule) {
|
|
21
|
+
JNIEnv *env, jobject /* this */, jlong jsRuntime,
|
|
22
|
+
jobject jsCallInvokerHolder, jobject blobModule) {
|
|
22
23
|
auto runtime = reinterpret_cast<facebook::jsi::Runtime *>(jsRuntime);
|
|
23
24
|
jobject globalBlobModule = env->NewGlobalRef(blobModule);
|
|
25
|
+
auto jsCallInvoker{
|
|
26
|
+
facebook::jni::alias_ref<facebook::react::CallInvokerHolder::javaobject>{
|
|
27
|
+
reinterpret_cast<facebook::react::CallInvokerHolder::javaobject>(
|
|
28
|
+
jsCallInvokerHolder)} -> cthis()
|
|
29
|
+
->getCallInvoker()};
|
|
24
30
|
auto platformContext =
|
|
25
31
|
std::make_shared<rnwgpu::AndroidPlatformContext>(globalBlobModule);
|
|
26
|
-
manager = std::make_shared<rnwgpu::RNWebGPUManager>(runtime,
|
|
32
|
+
manager = std::make_shared<rnwgpu::RNWebGPUManager>(runtime, jsCallInvoker,
|
|
27
33
|
platformContext);
|
|
28
34
|
}
|
|
29
35
|
|
|
@@ -55,7 +61,7 @@ Java_com_webgpu_WebGPUView_switchToOffscreenSurface(JNIEnv *env, jobject thiz,
|
|
|
55
61
|
jint contextId) {
|
|
56
62
|
auto ®istry = rnwgpu::SurfaceRegistry::getInstance();
|
|
57
63
|
auto nativeSurface = registry.getSurfaceInfo(contextId)->switchToOffscreen();
|
|
58
|
-
ANativeWindow_release(reinterpret_cast<ANativeWindow *>(nativeSurface));
|
|
64
|
+
// ANativeWindow_release(reinterpret_cast<ANativeWindow *>(nativeSurface));
|
|
59
65
|
}
|
|
60
66
|
|
|
61
67
|
extern "C" JNIEXPORT void JNICALL Java_com_webgpu_WebGPUView_onSurfaceDestroy(
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
//
|
|
2
|
+
// ThreadUtils.cpp
|
|
3
|
+
// react-native-nitro
|
|
4
|
+
//
|
|
5
|
+
// Created by Marc Rousavy on 14.07.24.
|
|
6
|
+
//
|
|
7
|
+
|
|
8
|
+
#include "ThreadUtils.h"
|
|
9
|
+
#include <pthread.h>
|
|
10
|
+
#include <sstream>
|
|
11
|
+
#include <string>
|
|
12
|
+
#include <sys/prctl.h>
|
|
13
|
+
#include <thread>
|
|
14
|
+
|
|
15
|
+
namespace margelo {
|
|
16
|
+
|
|
17
|
+
std::string ThreadUtils::getThreadName() {
|
|
18
|
+
#ifdef HAVE_ANDROID_PTHREAD_SETNAME_NP
|
|
19
|
+
// Try using pthread APIs
|
|
20
|
+
pthread_t this_thread = pthread_self();
|
|
21
|
+
char thread_name[16]; // Thread name length limit in Android is 16 characters
|
|
22
|
+
|
|
23
|
+
int result =
|
|
24
|
+
pthread_getname_np(this_thread, thread_name, sizeof(thread_name));
|
|
25
|
+
if (result == 0) {
|
|
26
|
+
return std::string(thread_name);
|
|
27
|
+
}
|
|
28
|
+
#endif
|
|
29
|
+
|
|
30
|
+
// Fall back to this_thread ID
|
|
31
|
+
std::stringstream stream;
|
|
32
|
+
stream << std::this_thread::get_id();
|
|
33
|
+
std::string threadId = stream.str();
|
|
34
|
+
return "Thread #" + threadId;
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
void ThreadUtils::setThreadName(const std::string &name) {
|
|
38
|
+
prctl(PR_SET_NAME, name.c_str(), 0, 0, 0);
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
} // namespace margelo
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
//
|
|
2
|
+
// ThreadUtils.cpp
|
|
3
|
+
// react-native-nitro
|
|
4
|
+
//
|
|
5
|
+
// Created by Marc Rousavy on 14.07.24.
|
|
6
|
+
//
|
|
7
|
+
|
|
8
|
+
#include "ThreadUtils.h"
|
|
9
|
+
#include <pthread.h>
|
|
10
|
+
#include <sstream>
|
|
11
|
+
#include <thread>
|
|
12
|
+
|
|
13
|
+
namespace margelo {
|
|
14
|
+
|
|
15
|
+
std::string ThreadUtils::getThreadName() {
|
|
16
|
+
// Try using pthread APIs
|
|
17
|
+
char name[256];
|
|
18
|
+
if (pthread_getname_np(pthread_self(), name, sizeof(name)) == 0) {
|
|
19
|
+
return std::string(name);
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
// Fall back to this_thread ID
|
|
23
|
+
std::stringstream stream;
|
|
24
|
+
stream << std::this_thread::get_id();
|
|
25
|
+
std::string threadId = stream.str();
|
|
26
|
+
return "Thread #" + threadId;
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
void ThreadUtils::setThreadName(const std::string &name) {
|
|
30
|
+
pthread_setname_np(name.c_str());
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
} // namespace margelo
|
|
@@ -25,6 +25,9 @@
|
|
|
25
25
|
#include "RNFPromise.h"
|
|
26
26
|
#include "RNFWorkletRuntimeRegistry.h"
|
|
27
27
|
|
|
28
|
+
#include "Dispatcher.h"
|
|
29
|
+
#include "ThreadPool.h"
|
|
30
|
+
|
|
28
31
|
#if __has_include(<cxxabi.h>)
|
|
29
32
|
#include <cxxabi.h>
|
|
30
33
|
#endif
|
|
@@ -207,39 +210,55 @@ template <typename TResult> struct JSIConverter<std::future<TResult>> {
|
|
|
207
210
|
}
|
|
208
211
|
static jsi::Value toJSI(jsi::Runtime& runtime, std::future<TResult>&& arg) {
|
|
209
212
|
auto sharedFuture = std::make_shared<std::future<TResult>>(std::move(arg));
|
|
210
|
-
|
|
213
|
+
std::shared_ptr<Dispatcher> strongDispatcher = Dispatcher::getRuntimeGlobalDispatcher(runtime);
|
|
214
|
+
std::weak_ptr<Dispatcher> weakDispatcher = strongDispatcher;
|
|
215
|
+
|
|
216
|
+
return Promise::createPromise(runtime, [sharedFuture = std::move(sharedFuture), weakDispatcher](jsi::Runtime& runtime,
|
|
211
217
|
std::shared_ptr<Promise> promise) {
|
|
212
|
-
|
|
213
|
-
|
|
218
|
+
// Spawn new async thread to synchronously wait for the `future<T>` to complete
|
|
219
|
+
std::shared_ptr<ThreadPool> pool = ThreadPool::getSharedPool();
|
|
220
|
+
pool->run([promise, &runtime, weakDispatcher, sharedFuture]() {
|
|
221
|
+
// synchronously wait until the `future<T>` completes. we are running on a background task here.
|
|
214
222
|
sharedFuture->wait();
|
|
215
223
|
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
} else {
|
|
221
|
-
// it's returning a custom type, convert it to a jsi::Value
|
|
222
|
-
TResult result = sharedFuture->get();
|
|
223
|
-
jsi::Value jsResult = JSIConverter<TResult>::toJSI(runtime, result);
|
|
224
|
-
promise->resolve(std::move(jsResult));
|
|
224
|
+
std::shared_ptr<Dispatcher> dispatcher = weakDispatcher.lock();
|
|
225
|
+
if (!dispatcher) {
|
|
226
|
+
throw std::runtime_error("Tried resolving Promise on JS Thread, but the `Dispatcher` has already been destroyed!");
|
|
227
|
+
return;
|
|
225
228
|
}
|
|
226
|
-
} catch (const std::exception& exception) {
|
|
227
|
-
// the async function threw an error, reject the promise
|
|
228
|
-
std::string what = exception.what();
|
|
229
|
-
promise->reject(what);
|
|
230
|
-
} catch (...) {
|
|
231
|
-
// the async function threw a non-std error, try getting it
|
|
232
|
-
#if __has_include(<cxxabi.h>)
|
|
233
|
-
std::string name = __cxxabiv1::__cxa_current_exception_type()->name();
|
|
234
|
-
#else
|
|
235
|
-
std::string name = "<unknown>";
|
|
236
|
-
#endif
|
|
237
|
-
promise->reject("Unknown non-std exception: " + name);
|
|
238
|
-
}
|
|
239
229
|
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
230
|
+
dispatcher->runAsync([&runtime, promise, sharedFuture]() mutable {
|
|
231
|
+
try {
|
|
232
|
+
if constexpr (std::is_same_v<TResult, void>) {
|
|
233
|
+
// it's returning void, just return undefined to JS
|
|
234
|
+
sharedFuture->get();
|
|
235
|
+
promise->resolve(jsi::Value::undefined());
|
|
236
|
+
} else {
|
|
237
|
+
// it's returning a custom type, convert it to a jsi::Value
|
|
238
|
+
TResult result = sharedFuture->get();
|
|
239
|
+
jsi::Value jsResult = JSIConverter<TResult>::toJSI(runtime, result);
|
|
240
|
+
promise->resolve(std::move(jsResult));
|
|
241
|
+
}
|
|
242
|
+
} catch (const std::exception& exception) {
|
|
243
|
+
// the async function threw an error, reject the promise
|
|
244
|
+
std::string what = exception.what();
|
|
245
|
+
promise->reject(what);
|
|
246
|
+
} catch (...) {
|
|
247
|
+
// the async function threw a non-std error, try getting it
|
|
248
|
+
#if __has_include(<cxxabi.h>)
|
|
249
|
+
std::string name = __cxxabiv1::__cxa_current_exception_type()->name();
|
|
250
|
+
#else
|
|
251
|
+
std::string name = "<unknown>";
|
|
252
|
+
#endif
|
|
253
|
+
promise->reject("Unknown non-std exception: " + name);
|
|
254
|
+
}
|
|
255
|
+
|
|
256
|
+
// This lambda owns the promise shared pointer, and we need to call its
|
|
257
|
+
// destructor correctly here - otherwise it might be called
|
|
258
|
+
// from the threadPool thread.
|
|
259
|
+
promise = nullptr;
|
|
260
|
+
});
|
|
261
|
+
});
|
|
243
262
|
});
|
|
244
263
|
}
|
|
245
264
|
};
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
//
|
|
2
|
+
// ThreadUtils.hpp
|
|
3
|
+
// react-native-nitro
|
|
4
|
+
//
|
|
5
|
+
// Created by Marc Rousavy on 14.07.24.
|
|
6
|
+
//
|
|
7
|
+
#pragma once
|
|
8
|
+
|
|
9
|
+
#include <string>
|
|
10
|
+
|
|
11
|
+
namespace margelo {
|
|
12
|
+
|
|
13
|
+
class ThreadUtils final {
|
|
14
|
+
public:
|
|
15
|
+
ThreadUtils() = delete;
|
|
16
|
+
|
|
17
|
+
/**
|
|
18
|
+
* Get the current Thread's name.
|
|
19
|
+
* This is implemented differently on iOS and Android.
|
|
20
|
+
*/
|
|
21
|
+
static std::string getThreadName();
|
|
22
|
+
|
|
23
|
+
/**
|
|
24
|
+
* Set the current Thread's name.
|
|
25
|
+
* This is implemented differently on iOS and Android.
|
|
26
|
+
*/
|
|
27
|
+
static void setThreadName(const std::string &name);
|
|
28
|
+
};
|
|
29
|
+
|
|
30
|
+
} // namespace margelo
|
|
@@ -1,5 +1,7 @@
|
|
|
1
1
|
#include "RNWebGPUManager.h"
|
|
2
2
|
|
|
3
|
+
#include "CallInvokerDispatcher.h"
|
|
4
|
+
#include "Dispatcher.h"
|
|
3
5
|
#include "GPU.h"
|
|
4
6
|
#include "RNWebGPU.h"
|
|
5
7
|
|
|
@@ -22,6 +24,12 @@ RNWebGPUManager::RNWebGPUManager(
|
|
|
22
24
|
: _jsRuntime(jsRuntime), _jsCallInvoker(jsCallInvoker),
|
|
23
25
|
_platformContext(platformContext) {
|
|
24
26
|
|
|
27
|
+
// Installs the global Dispatcher mechanism into this Runtime.
|
|
28
|
+
// This allows creating Promises and calling back to JS.
|
|
29
|
+
auto dispatcher =
|
|
30
|
+
std::make_shared<margelo::CallInvokerDispatcher>(_jsCallInvoker);
|
|
31
|
+
margelo::Dispatcher::installRuntimeGlobalDispatcher(*_jsRuntime, dispatcher);
|
|
32
|
+
|
|
25
33
|
auto gpu = std::make_shared<GPU>();
|
|
26
34
|
auto rnWebGPU = std::make_shared<RNWebGPU>(gpu, _platformContext);
|
|
27
35
|
_gpu = gpu->get();
|
|
@@ -175,6 +175,17 @@ public:
|
|
|
175
175
|
return true;
|
|
176
176
|
}
|
|
177
177
|
|
|
178
|
+
[[nodiscard]] bool Convert(wgpu::OptionalBool &out,
|
|
179
|
+
const std::optional<bool> &in) {
|
|
180
|
+
out = in;
|
|
181
|
+
return true;
|
|
182
|
+
}
|
|
183
|
+
|
|
184
|
+
[[nodiscard]] bool Convert(wgpu::StringView &out, const std::string &in) {
|
|
185
|
+
out = {in.data(), in.size()};
|
|
186
|
+
return true;
|
|
187
|
+
}
|
|
188
|
+
|
|
178
189
|
[[nodiscard]] bool Convert(const char *&out, const std::string &in) {
|
|
179
190
|
out = in.c_str();
|
|
180
191
|
return true;
|
|
@@ -481,11 +492,8 @@ public:
|
|
|
481
492
|
const GPUPrimitiveState &in) {
|
|
482
493
|
out = {};
|
|
483
494
|
|
|
484
|
-
if (in.unclippedDepth) {
|
|
485
|
-
|
|
486
|
-
Allocate<wgpu::PrimitiveDepthClipControl>();
|
|
487
|
-
depthClip->unclippedDepth = true;
|
|
488
|
-
out.nextInChain = depthClip;
|
|
495
|
+
if (in.unclippedDepth.has_value()) {
|
|
496
|
+
out.unclippedDepth = in.unclippedDepth.value();
|
|
489
497
|
}
|
|
490
498
|
|
|
491
499
|
return Convert(out.topology, in.topology) &&
|
package/cpp/rnwgpu/api/GPU.cpp
CHANGED
|
@@ -28,10 +28,10 @@ GPU::requestAdapter(
|
|
|
28
28
|
wgpu::Adapter adapter = nullptr;
|
|
29
29
|
_instance.RequestAdapter(
|
|
30
30
|
&aOptions,
|
|
31
|
-
[](WGPURequestAdapterStatus, WGPUAdapter cAdapter,
|
|
32
|
-
void *userdata) {
|
|
33
|
-
if (message
|
|
34
|
-
fprintf(stderr, "%s", message);
|
|
31
|
+
[](WGPURequestAdapterStatus, WGPUAdapter cAdapter,
|
|
32
|
+
const WGPUStringView message, void *userdata) {
|
|
33
|
+
if (message.length) {
|
|
34
|
+
fprintf(stderr, "%s", message.data);
|
|
35
35
|
return;
|
|
36
36
|
}
|
|
37
37
|
*static_cast<wgpu::Adapter *>(userdata) =
|
|
@@ -23,7 +23,7 @@ std::future<std::shared_ptr<GPUDevice>> GPUAdapter::requestDevice(
|
|
|
23
23
|
}
|
|
24
24
|
wgpu::DeviceLostCallbackInfo info = {
|
|
25
25
|
.callback = [](WGPUDevice const *device, WGPUDeviceLostReason reason,
|
|
26
|
-
|
|
26
|
+
const WGPUStringView message, void *userdata) {
|
|
27
27
|
const char *lostReason = "";
|
|
28
28
|
switch (reason) {
|
|
29
29
|
case WGPUDeviceLostReason_Destroyed:
|
|
@@ -35,12 +35,13 @@ std::future<std::shared_ptr<GPUDevice>> GPUAdapter::requestDevice(
|
|
|
35
35
|
default:
|
|
36
36
|
lostReason = "Unknown";
|
|
37
37
|
}
|
|
38
|
-
Logger::logToConsole("GPU Device Lost (%s): %s", lostReason,
|
|
38
|
+
Logger::logToConsole("GPU Device Lost (%s): %s", lostReason,
|
|
39
|
+
message.data);
|
|
39
40
|
}};
|
|
40
41
|
aDescriptor.deviceLostCallbackInfo = info;
|
|
41
42
|
wgpu::UncapturedErrorCallbackInfo errorInfo;
|
|
42
43
|
errorInfo.userdata = static_cast<void *>(_creationRuntime);
|
|
43
|
-
errorInfo.callback = [](WGPUErrorType type, const
|
|
44
|
+
errorInfo.callback = [](WGPUErrorType type, const WGPUStringView message,
|
|
44
45
|
void *userdata) {
|
|
45
46
|
auto creationRuntime = static_cast<jsi::Runtime *>(userdata);
|
|
46
47
|
const char *errorType = "";
|
|
@@ -60,16 +61,16 @@ std::future<std::shared_ptr<GPUDevice>> GPUAdapter::requestDevice(
|
|
|
60
61
|
default:
|
|
61
62
|
errorType = "Unknown";
|
|
62
63
|
}
|
|
63
|
-
std::string fullMessage = std::string(errorType) + ": " + message;
|
|
64
|
-
Logger::errorToJavascriptConsole(*creationRuntime, fullMessage
|
|
64
|
+
std::string fullMessage = std::string(errorType) + ": " + message.data;
|
|
65
|
+
Logger::errorToJavascriptConsole(*creationRuntime, fullMessage);
|
|
65
66
|
};
|
|
66
67
|
aDescriptor.uncapturedErrorCallbackInfo = errorInfo;
|
|
67
68
|
_instance.RequestDevice(
|
|
68
69
|
&aDescriptor,
|
|
69
70
|
[](WGPURequestDeviceStatus status, WGPUDevice cDevice,
|
|
70
|
-
const
|
|
71
|
-
if (message
|
|
72
|
-
fprintf(stderr, "%s", message);
|
|
71
|
+
const WGPUStringView message, void *userdata) {
|
|
72
|
+
if (message.length) {
|
|
73
|
+
fprintf(stderr, "%s", message.data);
|
|
73
74
|
return;
|
|
74
75
|
}
|
|
75
76
|
*static_cast<wgpu::Device *>(userdata) = wgpu::Device::Acquire(cDevice);
|
|
@@ -80,17 +81,17 @@ std::future<std::shared_ptr<GPUDevice>> GPUAdapter::requestDevice(
|
|
|
80
81
|
throw std::runtime_error("Failed to request device");
|
|
81
82
|
}
|
|
82
83
|
device.SetLoggingCallback(
|
|
83
|
-
[](WGPULoggingType type, const
|
|
84
|
+
[](WGPULoggingType type, const WGPUStringView message, void *userdata) {
|
|
84
85
|
auto creationRuntime = static_cast<jsi::Runtime *>(userdata);
|
|
85
86
|
const char *logLevel = "";
|
|
86
87
|
switch (type) {
|
|
87
88
|
case WGPULoggingType_Warning:
|
|
88
89
|
logLevel = "Warning";
|
|
89
|
-
Logger::warnToJavascriptConsole(*creationRuntime, message);
|
|
90
|
+
Logger::warnToJavascriptConsole(*creationRuntime, message.data);
|
|
90
91
|
break;
|
|
91
92
|
case WGPULoggingType_Error:
|
|
92
93
|
logLevel = "Error";
|
|
93
|
-
Logger::errorToJavascriptConsole(*creationRuntime, message);
|
|
94
|
+
Logger::errorToJavascriptConsole(*creationRuntime, message.data);
|
|
94
95
|
break;
|
|
95
96
|
case WGPULoggingType_Verbose:
|
|
96
97
|
logLevel = "Verbose";
|
|
@@ -139,9 +140,9 @@ std::shared_ptr<GPUAdapterInfo> GPUAdapter::getInfo() {
|
|
|
139
140
|
}
|
|
140
141
|
|
|
141
142
|
bool GPUAdapter::getIsFallbackAdapter() {
|
|
142
|
-
wgpu::
|
|
143
|
-
_instance.
|
|
144
|
-
return
|
|
143
|
+
wgpu::AdapterInfo adapterInfo = {};
|
|
144
|
+
_instance.GetInfo(&adapterInfo);
|
|
145
|
+
return adapterInfo.adapterType == wgpu::AdapterType::CPU;
|
|
145
146
|
}
|
|
146
147
|
|
|
147
148
|
} // namespace rnwgpu
|
|
@@ -8,6 +8,7 @@
|
|
|
8
8
|
#include "RNFHybridObject.h"
|
|
9
9
|
|
|
10
10
|
#include "AsyncRunner.h"
|
|
11
|
+
#include "Convertors.h"
|
|
11
12
|
|
|
12
13
|
#include "webgpu/webgpu_cpp.h"
|
|
13
14
|
|
|
@@ -23,10 +24,30 @@ public:
|
|
|
23
24
|
public:
|
|
24
25
|
std::string getBrand() { return _name; }
|
|
25
26
|
|
|
26
|
-
std::string getVendor() {
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
27
|
+
std::string getVendor() {
|
|
28
|
+
if (_instance.vendor.length) {
|
|
29
|
+
return _instance.vendor.data;
|
|
30
|
+
}
|
|
31
|
+
return "";
|
|
32
|
+
}
|
|
33
|
+
std::string getArchitecture() {
|
|
34
|
+
if (_instance.architecture.length) {
|
|
35
|
+
return _instance.architecture.data;
|
|
36
|
+
}
|
|
37
|
+
return "";
|
|
38
|
+
}
|
|
39
|
+
std::string getDevice() {
|
|
40
|
+
if (_instance.device.length) {
|
|
41
|
+
return _instance.device.data;
|
|
42
|
+
}
|
|
43
|
+
return "";
|
|
44
|
+
}
|
|
45
|
+
std::string getDescription() {
|
|
46
|
+
if (_instance.device.length) {
|
|
47
|
+
return _instance.device.data;
|
|
48
|
+
}
|
|
49
|
+
return "";
|
|
50
|
+
}
|
|
30
51
|
|
|
31
52
|
void loadHybridMethods() override {
|
|
32
53
|
registerHybridGetter("__brand", &GPUAdapterInfo::getBrand, this);
|
|
@@ -16,8 +16,9 @@ void GPUCanvasContext::configure(
|
|
|
16
16
|
throw std::runtime_error("Error with SurfaceConfiguration");
|
|
17
17
|
}
|
|
18
18
|
}
|
|
19
|
-
if (!conv(surfaceConfiguration.usage, configuration->usage) ||
|
|
20
|
-
|
|
19
|
+
if (!conv(surfaceConfiguration.usage, configuration->usage) ||
|
|
20
|
+
!conv(surfaceConfiguration.format, configuration->format)) {
|
|
21
|
+
throw std::runtime_error("Error with SurfaceConfiguration");
|
|
21
22
|
}
|
|
22
23
|
|
|
23
24
|
#ifdef __APPLE__
|
|
@@ -76,10 +76,9 @@ std::shared_ptr<GPUShaderModule> GPUDevice::createShaderModule(
|
|
|
76
76
|
}
|
|
77
77
|
sm_desc.nextInChain = &wgsl_desc;
|
|
78
78
|
if (descriptor->code.find('\0') != std::string::npos) {
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
_async, sm_desc.label);
|
|
79
|
+
auto mod = _instance.CreateErrorShaderModule(
|
|
80
|
+
&sm_desc, "The WGSL shader contains an illegal character '\\0'");
|
|
81
|
+
return std::make_shared<GPUShaderModule>(mod, _async, sm_desc.label.data);
|
|
83
82
|
}
|
|
84
83
|
auto module = _instance.CreateShaderModule(&sm_desc);
|
|
85
84
|
return std::make_shared<GPUShaderModule>(module, _async,
|
|
@@ -337,6 +336,7 @@ std::unordered_set<std::string> GPUDevice::getFeatures() {
|
|
|
337
336
|
}
|
|
338
337
|
|
|
339
338
|
std::future<std::shared_ptr<GPUDeviceLostInfo>> GPUDevice::getLost() {
|
|
340
|
-
return
|
|
339
|
+
return std::async(std::launch::async,
|
|
340
|
+
[=]() { return m_lostSharedFuture->get(); });
|
|
341
341
|
}
|
|
342
342
|
} // namespace rnwgpu
|
|
@@ -57,6 +57,10 @@ public:
|
|
|
57
57
|
_label(label) {
|
|
58
58
|
m_lostPromise =
|
|
59
59
|
std::make_shared<std::promise<std::shared_ptr<GPUDeviceLostInfo>>>();
|
|
60
|
+
|
|
61
|
+
auto sharedFuture = m_lostPromise->get_future().share();
|
|
62
|
+
m_lostSharedFuture = std::make_shared<
|
|
63
|
+
std::shared_future<std::shared_ptr<GPUDeviceLostInfo>>>(sharedFuture);
|
|
60
64
|
}
|
|
61
65
|
|
|
62
66
|
public:
|
|
@@ -154,6 +158,8 @@ private:
|
|
|
154
158
|
std::string _label;
|
|
155
159
|
std::shared_ptr<std::promise<std::shared_ptr<GPUDeviceLostInfo>>>
|
|
156
160
|
m_lostPromise;
|
|
161
|
+
std::shared_ptr<std::shared_future<std::shared_ptr<GPUDeviceLostInfo>>>
|
|
162
|
+
m_lostSharedFuture;
|
|
157
163
|
};
|
|
158
164
|
|
|
159
|
-
} // namespace rnwgpu
|
|
165
|
+
} // namespace rnwgpu
|
|
@@ -65,9 +65,9 @@ static void convertEnumToJSUnion(wgpu::FeatureName inEnum,
|
|
|
65
65
|
case wgpu::FeatureName::ImplicitDeviceSynchronization:
|
|
66
66
|
*outUnion = "implicit-device-synchronization";
|
|
67
67
|
break;
|
|
68
|
-
case wgpu::FeatureName::SurfaceCapabilities:
|
|
69
|
-
*outUnion = "surface-capabilities";
|
|
70
|
-
break;
|
|
68
|
+
// case wgpu::FeatureName::SurfaceCapabilities:
|
|
69
|
+
// *outUnion = "surface-capabilities";
|
|
70
|
+
// break;
|
|
71
71
|
case wgpu::FeatureName::TransientAttachments:
|
|
72
72
|
*outUnion = "transient-attachments";
|
|
73
73
|
break;
|
|
@@ -218,4 +218,4 @@ static void convertEnumToJSUnion(wgpu::FeatureName inEnum,
|
|
|
218
218
|
}
|
|
219
219
|
}
|
|
220
220
|
|
|
221
|
-
} // namespace rnwgpu
|
|
221
|
+
} // namespace rnwgpu
|
|
@@ -18,7 +18,8 @@ GPUShaderModule::getCompilationInfo() {
|
|
|
18
18
|
for (size_t i = 0; i < compilationInfo->messageCount; ++i) {
|
|
19
19
|
const auto &wgpuMessage = compilationInfo->messages[i];
|
|
20
20
|
GPUCompilationMessage message;
|
|
21
|
-
message.message =
|
|
21
|
+
message.message =
|
|
22
|
+
wgpuMessage.message.length ? wgpuMessage.message.data : "";
|
|
22
23
|
message.type = wgpuMessage.type;
|
|
23
24
|
message.lineNum = wgpuMessage.lineNum;
|
|
24
25
|
message.linePos = wgpuMessage.linePos;
|
|
@@ -60,7 +60,9 @@ struct JSIConverter<std::shared_ptr<rnwgpu::GPUCanvasConfiguration>> {
|
|
|
60
60
|
false);
|
|
61
61
|
}
|
|
62
62
|
if (value.hasProperty(runtime, "alphaMode")) {
|
|
63
|
-
auto prop = value.getProperty(runtime, "alphaMode")
|
|
63
|
+
auto prop = value.getProperty(runtime, "alphaMode")
|
|
64
|
+
.asString(runtime)
|
|
65
|
+
.utf8(runtime);
|
|
64
66
|
if (prop == "premultiplied") {
|
|
65
67
|
result->alphaMode = wgpu::CompositeAlphaMode::Premultiplied;
|
|
66
68
|
}
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
|
|
2
|
+
//
|
|
3
|
+
// Created by Marc Rousavy on 27.03.24.
|
|
4
|
+
//
|
|
5
|
+
|
|
6
|
+
#pragma once
|
|
7
|
+
|
|
8
|
+
#include "Dispatcher.h"
|
|
9
|
+
|
|
10
|
+
#include <utility>
|
|
11
|
+
#include <memory>
|
|
12
|
+
#include <ReactCommon/CallInvoker.h>
|
|
13
|
+
|
|
14
|
+
namespace margelo {
|
|
15
|
+
|
|
16
|
+
/**
|
|
17
|
+
* A Dispatcher that uses react::CallInvoker for it's implementation
|
|
18
|
+
*/
|
|
19
|
+
class CallInvokerDispatcher final : public Dispatcher {
|
|
20
|
+
public:
|
|
21
|
+
explicit CallInvokerDispatcher(
|
|
22
|
+
std::shared_ptr<react::CallInvoker> callInvoker)
|
|
23
|
+
: _callInvoker(callInvoker) {}
|
|
24
|
+
|
|
25
|
+
void runAsync(std::function<void()> &&function) override {
|
|
26
|
+
_callInvoker->invokeAsync(std::move(function));
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
void runSync(std::function<void()> &&function) override {
|
|
30
|
+
_callInvoker->invokeSync(std::move(function));
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
private:
|
|
34
|
+
std::shared_ptr<react::CallInvoker> _callInvoker;
|
|
35
|
+
};
|
|
36
|
+
|
|
37
|
+
} // namespace margelo
|