forked from wcandillon/react-native-webgpu
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathGPUSharedTextureMemory.cpp
More file actions
129 lines (113 loc) · 4.63 KB
/
Copy pathGPUSharedTextureMemory.cpp
File metadata and controls
129 lines (113 loc) · 4.63 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
#include "GPUSharedTextureMemory.h"
#include <memory>
#include <stdexcept>
#include <string>
#include "Convertors.h"
namespace rnwgpu {
std::shared_ptr<GPUTexture> GPUSharedTextureMemory::createTexture(
std::optional<std::shared_ptr<GPUTextureDescriptor>> descriptor) {
if (!descriptor.has_value() || descriptor.value() == nullptr) {
auto texture = _instance.CreateTexture();
return std::make_shared<GPUTexture>(texture, "");
}
wgpu::TextureDescriptor desc{};
Convertor conv;
if (!conv(desc, descriptor.value())) {
throw std::runtime_error(
"GPUSharedTextureMemory::createTexture(): Error with "
"GPUTextureDescriptor");
}
auto texture = _instance.CreateTexture(&desc);
return std::make_shared<GPUTexture>(texture,
descriptor.value()->label.value_or(""));
}
void GPUSharedTextureMemory::beginAccess(
std::shared_ptr<GPUTexture> texture, bool initialized,
std::optional<std::vector<std::shared_ptr<GPUSharedFenceState>>> fences) {
if (!texture) {
throw std::runtime_error(
"GPUSharedTextureMemory::beginAccess(): texture is null");
}
wgpu::SharedTextureMemoryBeginAccessDescriptor desc{};
desc.initialized = initialized;
desc.concurrentRead = false;
// Built in lockstep so fenceCount covers both arrays, and kept in locals so
// the raw pointers outlive the synchronous BeginAccess() below.
std::vector<wgpu::SharedFence> rawFences;
std::vector<uint64_t> values;
if (fences.has_value()) {
for (const auto &state : *fences) {
if (state && state->fence) {
rawFences.push_back(state->fence->get());
values.push_back(state->signaledValue);
}
}
}
if (!rawFences.empty()) {
desc.fenceCount = rawFences.size();
desc.fences = rawFences.data();
desc.signaledValues = values.data();
} else {
desc.fenceCount = 0;
desc.fences = nullptr;
desc.signaledValues = nullptr;
}
#if defined(__ANDROID__)
// Dawn's Vulkan backend (AHardwareBuffer) validates that the begin-access
// descriptor chains a SharedTextureMemoryVkImageLayoutBeginState specifying
// the VkImageLayout to acquire the image into. UNDEFINED (= 0) on both ends
// is the canonical "no prior GPU producer" pattern: Dawn performs an
// external-queue acquire from VK_QUEUE_FAMILY_EXTERNAL which preserves the
// AHB contents, then transitions to whatever layout the texture's actual
// usage requires.
wgpu::SharedTextureMemoryVkImageLayoutBeginState vkLayout{};
vkLayout.oldLayout = 0;
vkLayout.newLayout = 0;
desc.nextInChain = &vkLayout;
#endif
auto status = _instance.BeginAccess(texture->get(), &desc);
if (!status) {
throw std::runtime_error("GPUSharedTextureMemory::beginAccess() failed");
}
}
jsi::Value GPUSharedTextureMemory::endAccess(jsi::Runtime &runtime,
const jsi::Value &,
const jsi::Value *args,
size_t count) {
if (count < 1 || !args[0].isObject()) {
throw jsi::JSError(
runtime, "GPUSharedTextureMemory::endAccess(): expected (texture)");
}
auto texture = GPUTexture::fromValue(runtime, args[0]);
wgpu::SharedTextureMemoryEndAccessState state{};
#if defined(__ANDROID__)
// Dawn's Vulkan backend writes the released old/new VkImageLayouts back into
// a chained SharedTextureMemoryVkImageLayoutEndState; validation requires
// the chain even when the caller doesn't read the values.
wgpu::SharedTextureMemoryVkImageLayoutEndState vkLayout{};
state.nextInChain = &vkLayout;
#endif
auto status = _instance.EndAccess(texture->get(), &state);
if (!status) {
throw jsi::JSError(runtime, "GPUSharedTextureMemory::endAccess() failed");
}
// Copy each wgpu::SharedFence (ref-counted) into its own GPUSharedFence
// wrapper before `state` is destroyed.
jsi::Array fences(runtime, state.fenceCount);
for (size_t i = 0; i < state.fenceCount; i++) {
wgpu::SharedFence fence = state.fences[i];
auto wrapper = std::make_shared<GPUSharedFence>(std::move(fence), "");
jsi::Object entry(runtime);
entry.setProperty(runtime, "fence",
GPUSharedFence::create(runtime, std::move(wrapper)));
entry.setProperty(runtime, "signaledValue",
jsi::BigInt::fromUint64(runtime, state.signaledValues[i]));
fences.setValueAtIndex(runtime, i, std::move(entry));
}
jsi::Object result(runtime);
result.setProperty(runtime, "initialized",
jsi::Value(static_cast<bool>(state.initialized)));
result.setProperty(runtime, "fences", std::move(fences));
return result;
}
} // namespace rnwgpu