@@ -27,18 +27,38 @@ std::shared_ptr<GPUTexture> GPUSharedTextureMemory::createTexture(
2727 descriptor.value ()->label .value_or (" " ));
2828}
2929
30- bool GPUSharedTextureMemory::beginAccess (std::shared_ptr<GPUTexture> texture,
31- bool initialized) {
30+ void GPUSharedTextureMemory::beginAccess (
31+ std::shared_ptr<GPUTexture> texture, bool initialized,
32+ std::optional<std::vector<std::shared_ptr<GPUSharedFenceState>>> fences) {
3233 if (!texture) {
3334 throw std::runtime_error (
3435 " GPUSharedTextureMemory::beginAccess(): texture is null" );
3536 }
3637 wgpu::SharedTextureMemoryBeginAccessDescriptor desc{};
3738 desc.initialized = initialized;
3839 desc.concurrentRead = false ;
39- desc.fenceCount = 0 ;
40- desc.fences = nullptr ;
41- desc.signaledValues = nullptr ;
40+
41+ // Built in lockstep so fenceCount covers both arrays, and kept in locals so
42+ // the raw pointers outlive the synchronous BeginAccess() below.
43+ std::vector<wgpu::SharedFence> rawFences;
44+ std::vector<uint64_t > values;
45+ if (fences.has_value ()) {
46+ for (const auto &state : *fences) {
47+ if (state && state->fence ) {
48+ rawFences.push_back (state->fence ->get ());
49+ values.push_back (state->signaledValue );
50+ }
51+ }
52+ }
53+ if (!rawFences.empty ()) {
54+ desc.fenceCount = rawFences.size ();
55+ desc.fences = rawFences.data ();
56+ desc.signaledValues = values.data ();
57+ } else {
58+ desc.fenceCount = 0 ;
59+ desc.fences = nullptr ;
60+ desc.signaledValues = nullptr ;
61+ }
4262
4363#if defined(__ANDROID__)
4464 // Dawn's Vulkan backend (AHardwareBuffer) validates that the begin-access
@@ -55,14 +75,21 @@ bool GPUSharedTextureMemory::beginAccess(std::shared_ptr<GPUTexture> texture,
5575#endif
5676
5777 auto status = _instance.BeginAccess (texture->get (), &desc);
58- return static_cast <bool >(status);
78+ if (!status) {
79+ throw std::runtime_error (" GPUSharedTextureMemory::beginAccess() failed" );
80+ }
5981}
6082
61- bool GPUSharedTextureMemory::endAccess (std::shared_ptr<GPUTexture> texture) {
62- if (!texture) {
63- throw std::runtime_error (
64- " GPUSharedTextureMemory::endAccess(): texture is null" );
83+ jsi::Value GPUSharedTextureMemory::endAccess (jsi::Runtime &runtime,
84+ const jsi::Value &,
85+ const jsi::Value *args,
86+ size_t count) {
87+ if (count < 1 || !args[0 ].isObject ()) {
88+ throw jsi::JSError (
89+ runtime, " GPUSharedTextureMemory::endAccess(): expected (texture)" );
6590 }
91+ auto texture = GPUTexture::fromValue (runtime, args[0 ]);
92+
6693 wgpu::SharedTextureMemoryEndAccessState state{};
6794
6895#if defined(__ANDROID__)
@@ -74,7 +101,29 @@ bool GPUSharedTextureMemory::endAccess(std::shared_ptr<GPUTexture> texture) {
74101#endif
75102
76103 auto status = _instance.EndAccess (texture->get (), &state);
77- return static_cast <bool >(status);
104+ if (!status) {
105+ throw jsi::JSError (runtime, " GPUSharedTextureMemory::endAccess() failed" );
106+ }
107+
108+ // Copy each wgpu::SharedFence (ref-counted) into its own GPUSharedFence
109+ // wrapper before `state` is destroyed.
110+ jsi::Array fences (runtime, state.fenceCount );
111+ for (size_t i = 0 ; i < state.fenceCount ; i++) {
112+ wgpu::SharedFence fence = state.fences [i];
113+ auto wrapper = std::make_shared<GPUSharedFence>(std::move (fence), " " );
114+ jsi::Object entry (runtime);
115+ entry.setProperty (runtime, " fence" ,
116+ GPUSharedFence::create (runtime, std::move (wrapper)));
117+ entry.setProperty (runtime, " signaledValue" ,
118+ jsi::BigInt::fromUint64 (runtime, state.signaledValues [i]));
119+ fences.setValueAtIndex (runtime, i, std::move (entry));
120+ }
121+
122+ jsi::Object result (runtime);
123+ result.setProperty (runtime, " initialized" ,
124+ jsi::Value (static_cast <bool >(state.initialized )));
125+ result.setProperty (runtime, " fences" , std::move (fences));
126+ return result;
78127}
79128
80129} // namespace rnwgpu
0 commit comments