Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: Use setExternalMemoryPressure to notify JS VM about Frame's actual size (on GPU) #3098

Open
wants to merge 4 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 5 additions & 1 deletion package/VisionCamera.podspec
Original file line number Diff line number Diff line change
@@ -1,8 +1,11 @@
require "json"

package = JSON.parse(File.read(File.join(__dir__, "package.json")))
$config = find_config()

nodeModules = File.join(File.dirname(`cd "#{Pod::Config.instance.installation_root.to_s}" && node --print "require.resolve('react-native/package.json')"`), '..')
reactNativePackage = JSON.parse(File.read(File.join(nodeModules, "react-native", "package.json")))
reactNativeVersion = reactNativePackage["version"]

Pod::UI.puts "[VisionCamera] Thank you for using VisionCamera ❤️"
Pod::UI.puts "[VisionCamera] If you enjoy using VisionCamera, please consider sponsoring this project: https://github.com/sponsors/mrousavy"
Expand All @@ -24,6 +27,7 @@ else
end

Pod::UI.puts("[VisionCamera] node modules #{Dir.exist?(nodeModules) ? "found at #{nodeModules}" : "not found!"}")
Pod::UI.puts "[VisionCamera] React Native Version: 0.#{reactNativeVersion}"
workletsPath = File.join(nodeModules, "react-native-worklets-core")
hasWorklets = File.exist?(workletsPath)
if hasWorklets
Expand All @@ -46,7 +50,7 @@ Pod::Spec.new do |s|
s.source = { :git => "https://github.com/mrousavy/react-native-vision-camera.git", :tag => "#{s.version}" }

s.pod_target_xcconfig = {
"GCC_PREPROCESSOR_DEFINITIONS" => "$(inherited) VISION_CAMERA_ENABLE_FRAME_PROCESSORS=#{enableFrameProcessors}",
"GCC_PREPROCESSOR_DEFINITIONS" => "$(inherited) VISION_CAMERA_ENABLE_FRAME_PROCESSORS=#{enableFrameProcessors} REACT_NATIVE_VERSION=#{reactNativeVersion}",
"SWIFT_ACTIVE_COMPILATION_CONDITIONS" => "$(inherited) #{enableFrameProcessors ? "VISION_CAMERA_ENABLE_FRAME_PROCESSORS" : ""}",
}

Expand Down
16 changes: 8 additions & 8 deletions package/example/ios/Podfile.lock
Original file line number Diff line number Diff line change
Expand Up @@ -1391,16 +1391,16 @@ PODS:
- ReactCommon/turbomodule/core
- Yoga
- SocketRocket (0.7.0)
- VisionCamera (4.4.3):
- VisionCamera/Core (= 4.4.3)
- VisionCamera/FrameProcessors (= 4.4.3)
- VisionCamera/React (= 4.4.3)
- VisionCamera/Core (4.4.3)
- VisionCamera/FrameProcessors (4.4.3):
- VisionCamera (4.5.0):
- VisionCamera/Core (= 4.5.0)
- VisionCamera/FrameProcessors (= 4.5.0)
- VisionCamera/React (= 4.5.0)
- VisionCamera/Core (4.5.0)
- VisionCamera/FrameProcessors (4.5.0):
- React
- React-callinvoker
- react-native-worklets-core
- VisionCamera/React (4.4.3):
- VisionCamera/React (4.5.0):
- React-Core
- VisionCamera/FrameProcessors
- Yoga (0.0.0)
Expand Down Expand Up @@ -1688,7 +1688,7 @@ SPEC CHECKSUMS:
RNStaticSafeAreaInsets: 055ddbf5e476321720457cdaeec0ff2ba40ec1b8
RNVectorIcons: 2a2f79274248390b80684ea3c4400bd374a15c90
SocketRocket: abac6f5de4d4d62d24e11868d7a2f427e0ef940d
VisionCamera: 7435f20f7ee7756a1e307e986195a97764da5142
VisionCamera: dfdaf784ba5010e3351fb724a8aa6c8fc379018e
Yoga: 2f71ecf38d934aecb366e686278102a51679c308

PODFILE CHECKSUM: 49584be049764895189f1f88ebc9769116621103
Expand Down
2 changes: 0 additions & 2 deletions package/ios/FrameProcessors/FrameProcessor.h
Original file line number Diff line number Diff line change
Expand Up @@ -28,8 +28,6 @@ NS_ASSUME_NONNULL_BEGIN
#ifdef __cplusplus
- (instancetype _Nonnull)initWithWorklet:(std::shared_ptr<RNWorklet::JsiWorklet>)worklet
context:(std::shared_ptr<RNWorklet::JsiWorkletContext>)context;

- (void)callWithFrameHostObject:(std::shared_ptr<FrameHostObject>)frameHostObject;
#endif

- (void)call:(Frame*)frame;
Expand Down
15 changes: 3 additions & 12 deletions package/ios/FrameProcessors/FrameProcessor.mm
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
#import <Foundation/Foundation.h>

#import "FrameHostObject.h"
#import "JSINSObjectConversion.h"
#import "WKTJsiWorklet.h"
#import <jsi/jsi.h>
#import <memory>
Expand All @@ -30,25 +31,15 @@ - (instancetype)initWithWorklet:(std::shared_ptr<RNWorklet::JsiWorklet>)worklet
return self;
}

- (void)callWithFrameHostObject:(std::shared_ptr<FrameHostObject>)frameHostObject {
- (void)call:(Frame* _Nonnull)frame {
// Call the Frame Processor on the Worklet Runtime
jsi::Runtime& runtime = _workletContext->getWorkletRuntime();

// Use a jsi::Scope to indicate that all values allocated in a Frame Processor shall be picked up by GC if possible
jsi::Scope scope(runtime);

// Wrap HostObject as JSI Value
auto argument = jsi::Object::createFromHostObject(runtime, frameHostObject);
jsi::Value jsValue(std::move(argument));
jsi::Value jsValue = JSINSObjectConversion::convertObjCObjectToJSIValue(runtime, frame);

// Call the Worklet with the Frame JS Host Object as an argument
_workletInvoker->call(runtime, jsi::Value::undefined(), &jsValue, 1);
}

- (void)call:(Frame* _Nonnull)frame {
// Create the Frame Host Object wrapping the internal Frame
auto frameHostObject = std::make_shared<FrameHostObject>(frame);
[self callWithFrameHostObject:frameHostObject];
}

@end
19 changes: 12 additions & 7 deletions package/ios/FrameProcessors/JSINSObjectConversion.mm
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,18 @@
namespace JSINSObjectConversion {

jsi::Value convertObjCObjectToJSIValue(jsi::Runtime& runtime, id value) {
if (value == nil || value == (id)kCFNull) {
if ([value isKindOfClass:[Frame class]]) {
// Frame

Frame* frame = (Frame*)value;
auto frameHostObject = std::make_shared<FrameHostObject>(frame);
jsi::Object object = jsi::Object::createFromHostObject(runtime, frameHostObject);
#if REACT_NATIVE_VERSION >= 74
size_t frameSize = frame.bytesPerRow * frame.height;
object.setExternalMemoryPressure(runtime, frameSize);
#endif
return object;
} else if (value == nil || value == (id)kCFNull) {
// null

return jsi::Value::undefined();
Expand Down Expand Up @@ -67,12 +78,6 @@
result.setValueAtIndex(runtime, i, convertObjCObjectToJSIValue(runtime, value[i]));
}
return result;
} else if ([value isKindOfClass:[Frame class]]) {
// Frame

Frame* frame = (Frame*)value;
auto frameHostObject = std::make_shared<FrameHostObject>(frame);
return jsi::Object::createFromHostObject(runtime, frameHostObject);
} else if ([value isKindOfClass:[SharedArray class]]) {
// SharedArray

Expand Down
Loading