@next2d/builder 0.1.5 → 0.1.7
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 +15 -0
- package/dist/index.js +315 -3
- package/package.json +10 -8
- package/templates/xbox/CMakeLists.txt +124 -0
- package/templates/xbox/MicrosoftGame.config +36 -0
- package/templates/xbox/README.md +372 -0
- package/templates/xbox/cmake/FetchDawn.cmake +42 -0
- package/templates/xbox/cmake/FindV8.cmake +68 -0
- package/templates/xbox/js/bootstrap.js +143 -0
- package/templates/xbox/js/selftest.js +515 -0
- package/templates/xbox/src/AssetLoader.cpp +106 -0
- package/templates/xbox/src/AssetLoader.h +35 -0
- package/templates/xbox/src/EventLoop.cpp +162 -0
- package/templates/xbox/src/EventLoop.h +73 -0
- package/templates/xbox/src/HostContext.h +58 -0
- package/templates/xbox/src/bindings/Audio.cpp +320 -0
- package/templates/xbox/src/bindings/Bindings.h +75 -0
- package/templates/xbox/src/bindings/Canvas.cpp +171 -0
- package/templates/xbox/src/bindings/Canvas2D.cpp +462 -0
- package/templates/xbox/src/bindings/Console.cpp +52 -0
- package/templates/xbox/src/bindings/DomShims.cpp +221 -0
- package/templates/xbox/src/bindings/EventTarget.cpp +127 -0
- package/templates/xbox/src/bindings/EventTarget.h +17 -0
- package/templates/xbox/src/bindings/Fetch.cpp +149 -0
- package/templates/xbox/src/bindings/Gamepad.cpp +79 -0
- package/templates/xbox/src/bindings/Image.cpp +160 -0
- package/templates/xbox/src/bindings/ImageSource.h +26 -0
- package/templates/xbox/src/bindings/Network.cpp +303 -0
- package/templates/xbox/src/bindings/RasterCore.h +265 -0
- package/templates/xbox/src/bindings/Timers.cpp +87 -0
- package/templates/xbox/src/bindings/Video.cpp +235 -0
- package/templates/xbox/src/bindings/webgpu/WebGPU.cpp +1318 -0
- package/templates/xbox/src/bindings/webgpu/WebGPUCommon.h +119 -0
- package/templates/xbox/src/bindings/webgpu/WebGPUEnums.h +245 -0
- package/templates/xbox/src/gpu/DawnContext.cpp +170 -0
- package/templates/xbox/src/gpu/DawnContext.h +64 -0
- package/templates/xbox/src/main.cpp +368 -0
- package/templates/xbox/src/platform/AudioEngine.cpp +184 -0
- package/templates/xbox/src/platform/AudioEngine.h +65 -0
- package/templates/xbox/src/platform/GamepadManager.cpp +83 -0
- package/templates/xbox/src/platform/GamepadManager.h +40 -0
- package/templates/xbox/src/platform/ImageTypes.h +17 -0
- package/templates/xbox/src/platform/TextRasterizer.cpp +183 -0
- package/templates/xbox/src/platform/TextRasterizer.h +35 -0
- package/templates/xbox/src/platform/WicDecoder.cpp +63 -0
- package/templates/xbox/src/platform/WicDecoder.h +16 -0
- package/templates/xbox/src/v8/V8Runtime.cpp +285 -0
- package/templates/xbox/src/v8/V8Runtime.h +68 -0
- package/templates/xbox/src/v8/V8Util.h +56 -0
- package/templates/xbox/src/worker/WorkerRuntime.cpp +453 -0
- package/templates/xbox/src/worker/WorkerRuntime.h +108 -0
- package/templates/xbox/tests/check_local.sh +56 -0
- package/templates/xbox/tests/raster_test.cpp +279 -0
- package/templates/xbox/tests/windows_platform_test.cpp +187 -0
|
@@ -0,0 +1,1318 @@
|
|
|
1
|
+
// WebGPU (navigator.gpu) を Dawn へ橋渡しするバインディング本体。
|
|
2
|
+
// WebGPUCommon.h の «実装範囲» コメントを参照。
|
|
3
|
+
#include "bindings/Bindings.h"
|
|
4
|
+
#include "bindings/webgpu/WebGPUCommon.h"
|
|
5
|
+
#include "bindings/webgpu/WebGPUEnums.h"
|
|
6
|
+
|
|
7
|
+
#include "HostContext.h"
|
|
8
|
+
#include "gpu/DawnContext.h"
|
|
9
|
+
#include "bindings/ImageSource.h"
|
|
10
|
+
|
|
11
|
+
#include <cstring>
|
|
12
|
+
#include <map>
|
|
13
|
+
#include <vector>
|
|
14
|
+
|
|
15
|
+
namespace next2d {
|
|
16
|
+
namespace webgpu {
|
|
17
|
+
|
|
18
|
+
using v8util::Str;
|
|
19
|
+
using v8util::SetMethod;
|
|
20
|
+
using v8util::SetValue;
|
|
21
|
+
|
|
22
|
+
// 各 wgpu 型に対応する ObjectTemplate 群 (単一 isolate 前提)。
|
|
23
|
+
struct Templates {
|
|
24
|
+
v8::Global<v8::ObjectTemplate> adapter, device, queue, buffer, texture,
|
|
25
|
+
textureView, sampler, shaderModule, bindGroupLayout, bindGroup,
|
|
26
|
+
pipelineLayout, renderPipeline, commandEncoder, renderPass,
|
|
27
|
+
commandBuffer, canvasContext;
|
|
28
|
+
};
|
|
29
|
+
|
|
30
|
+
static std::map<v8::Isolate*, Templates> g_templates;
|
|
31
|
+
|
|
32
|
+
static Templates& Tmpl(v8::Isolate* isolate)
|
|
33
|
+
{
|
|
34
|
+
return g_templates[isolate];
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
template <typename T>
|
|
38
|
+
static v8::Local<v8::Object> WrapWith(v8::Isolate* isolate,
|
|
39
|
+
v8::Global<v8::ObjectTemplate>& g, T handle)
|
|
40
|
+
{
|
|
41
|
+
return Wrap<T>(isolate, g.Get(isolate), std::move(handle));
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
// メソッド付与済みのラップ (前方宣言。定義は device セクション付近)
|
|
45
|
+
static v8::Local<v8::Object> WrapBuffer(v8::Isolate*, wgpu::Buffer);
|
|
46
|
+
static v8::Local<v8::Object> WrapTexture(v8::Isolate*, wgpu::Texture);
|
|
47
|
+
static v8::Local<v8::Object> WrapTextureView(v8::Isolate*, wgpu::TextureView);
|
|
48
|
+
static v8::Local<v8::Object> WrapEncoder(v8::Isolate*, wgpu::CommandEncoder);
|
|
49
|
+
static v8::Local<v8::Object> WrapPipeline(v8::Isolate*, wgpu::RenderPipeline);
|
|
50
|
+
|
|
51
|
+
// ---------------------------------------------------------------------------
|
|
52
|
+
// GPUBuffer
|
|
53
|
+
// ---------------------------------------------------------------------------
|
|
54
|
+
static void Buffer_GetMappedRange(const v8::FunctionCallbackInfo<v8::Value>& args)
|
|
55
|
+
{
|
|
56
|
+
v8::Isolate* isolate = args.GetIsolate();
|
|
57
|
+
wgpu::Buffer& buffer = Unwrap<wgpu::Buffer>(args.This());
|
|
58
|
+
|
|
59
|
+
uint64_t offset = args.Length() > 0 && args[0]->IsNumber()
|
|
60
|
+
? static_cast<uint64_t>(args[0].As<v8::Number>()->Value()) : 0;
|
|
61
|
+
uint64_t size = args.Length() > 1 && args[1]->IsNumber()
|
|
62
|
+
? static_cast<uint64_t>(args[1].As<v8::Number>()->Value())
|
|
63
|
+
: (buffer.GetSize() - offset);
|
|
64
|
+
|
|
65
|
+
void* ptr = buffer.GetMappedRange(offset, static_cast<size_t>(size));
|
|
66
|
+
if (!ptr) {
|
|
67
|
+
args.GetReturnValue().Set(v8::ArrayBuffer::New(isolate, 0));
|
|
68
|
+
return;
|
|
69
|
+
}
|
|
70
|
+
// マップ領域を指す非所有 ArrayBuffer (unmap まで有効)
|
|
71
|
+
std::unique_ptr<v8::BackingStore> store = v8::ArrayBuffer::NewBackingStore(
|
|
72
|
+
ptr, static_cast<size_t>(size),
|
|
73
|
+
[](void*, size_t, void*) {}, nullptr);
|
|
74
|
+
args.GetReturnValue().Set(v8::ArrayBuffer::New(isolate, std::move(store)));
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
static void Buffer_Unmap(const v8::FunctionCallbackInfo<v8::Value>& args)
|
|
78
|
+
{
|
|
79
|
+
Unwrap<wgpu::Buffer>(args.This()).Unmap();
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
static void Buffer_Destroy(const v8::FunctionCallbackInfo<v8::Value>& args)
|
|
83
|
+
{
|
|
84
|
+
Unwrap<wgpu::Buffer>(args.This()).Destroy();
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
static void Buffer_MapAsync(const v8::FunctionCallbackInfo<v8::Value>& args)
|
|
88
|
+
{
|
|
89
|
+
v8::Isolate* isolate = args.GetIsolate();
|
|
90
|
+
v8::Local<v8::Context> ctx = isolate->GetCurrentContext();
|
|
91
|
+
wgpu::Buffer& buffer = Unwrap<wgpu::Buffer>(args.This());
|
|
92
|
+
|
|
93
|
+
wgpu::MapMode mode = static_cast<wgpu::MapMode>(
|
|
94
|
+
args.Length() > 0 ? static_cast<uint32_t>(args[0].As<v8::Number>()->Value()) : 0);
|
|
95
|
+
uint64_t offset = args.Length() > 1 && args[1]->IsNumber()
|
|
96
|
+
? static_cast<uint64_t>(args[1].As<v8::Number>()->Value()) : 0;
|
|
97
|
+
uint64_t size = args.Length() > 2 && args[2]->IsNumber()
|
|
98
|
+
? static_cast<uint64_t>(args[2].As<v8::Number>()->Value())
|
|
99
|
+
: (buffer.GetSize() - offset);
|
|
100
|
+
|
|
101
|
+
auto resolver = v8::Promise::Resolver::New(ctx).ToLocalChecked();
|
|
102
|
+
auto* persistent = new v8::Global<v8::Promise::Resolver>(isolate, resolver);
|
|
103
|
+
args.GetReturnValue().Set(resolver->GetPromise());
|
|
104
|
+
|
|
105
|
+
buffer.MapAsync(mode, offset, static_cast<size_t>(size),
|
|
106
|
+
wgpu::CallbackMode::AllowProcessEvents,
|
|
107
|
+
[isolate, persistent](wgpu::MapAsyncStatus status, wgpu::StringView) {
|
|
108
|
+
v8::HandleScope scope(isolate);
|
|
109
|
+
v8::Local<v8::Context> c = isolate->GetCurrentContext();
|
|
110
|
+
auto r = persistent->Get(isolate);
|
|
111
|
+
if (status == wgpu::MapAsyncStatus::Success) {
|
|
112
|
+
r->Resolve(c, v8::Undefined(isolate)).Check();
|
|
113
|
+
} else {
|
|
114
|
+
r->Reject(c, v8::Exception::Error(v8util::Str(isolate, "mapAsync failed"))).Check();
|
|
115
|
+
}
|
|
116
|
+
persistent->Reset();
|
|
117
|
+
delete persistent;
|
|
118
|
+
});
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
// ---------------------------------------------------------------------------
|
|
122
|
+
// GPUTexture
|
|
123
|
+
// ---------------------------------------------------------------------------
|
|
124
|
+
static void Texture_CreateView(const v8::FunctionCallbackInfo<v8::Value>& args)
|
|
125
|
+
{
|
|
126
|
+
v8::Isolate* isolate = args.GetIsolate();
|
|
127
|
+
wgpu::Texture& texture = Unwrap<wgpu::Texture>(args.This());
|
|
128
|
+
|
|
129
|
+
wgpu::TextureViewDescriptor desc = {};
|
|
130
|
+
if (args.Length() > 0 && args[0]->IsObject()) {
|
|
131
|
+
v8::Local<v8::Object> o = args[0].As<v8::Object>();
|
|
132
|
+
if (HasProp(isolate, o, "format")) {
|
|
133
|
+
desc.format = ToTextureFormat(webgpu::Str(isolate, o, "format"));
|
|
134
|
+
}
|
|
135
|
+
if (HasProp(isolate, o, "dimension")) {
|
|
136
|
+
desc.dimension = ToTextureViewDimension(webgpu::Str(isolate, o, "dimension"));
|
|
137
|
+
}
|
|
138
|
+
if (HasProp(isolate, o, "baseMipLevel")) desc.baseMipLevel = U32(isolate, o, "baseMipLevel");
|
|
139
|
+
if (HasProp(isolate, o, "mipLevelCount")) desc.mipLevelCount = U32(isolate, o, "mipLevelCount");
|
|
140
|
+
if (HasProp(isolate, o, "baseArrayLayer")) desc.baseArrayLayer = U32(isolate, o, "baseArrayLayer");
|
|
141
|
+
if (HasProp(isolate, o, "arrayLayerCount")) desc.arrayLayerCount = U32(isolate, o, "arrayLayerCount");
|
|
142
|
+
}
|
|
143
|
+
args.GetReturnValue().Set(WrapTextureView(isolate, texture.CreateView(&desc)));
|
|
144
|
+
}
|
|
145
|
+
|
|
146
|
+
static void Texture_Destroy(const v8::FunctionCallbackInfo<v8::Value>& args)
|
|
147
|
+
{
|
|
148
|
+
Unwrap<wgpu::Texture>(args.This()).Destroy();
|
|
149
|
+
}
|
|
150
|
+
|
|
151
|
+
// ---------------------------------------------------------------------------
|
|
152
|
+
// GPUQueue
|
|
153
|
+
// ---------------------------------------------------------------------------
|
|
154
|
+
static bool CopyBytesFrom(v8::Local<v8::Value> value, const void** data, size_t* length)
|
|
155
|
+
{
|
|
156
|
+
if (value->IsArrayBuffer()) {
|
|
157
|
+
auto ab = value.As<v8::ArrayBuffer>();
|
|
158
|
+
auto store = ab->GetBackingStore();
|
|
159
|
+
*data = store->Data();
|
|
160
|
+
*length = store->ByteLength();
|
|
161
|
+
return true;
|
|
162
|
+
}
|
|
163
|
+
if (value->IsArrayBufferView()) {
|
|
164
|
+
auto view = value.As<v8::ArrayBufferView>();
|
|
165
|
+
auto ab = view->Buffer();
|
|
166
|
+
auto store = ab->GetBackingStore();
|
|
167
|
+
*data = static_cast<uint8_t*>(store->Data()) + view->ByteOffset();
|
|
168
|
+
*length = view->ByteLength();
|
|
169
|
+
return true;
|
|
170
|
+
}
|
|
171
|
+
return false;
|
|
172
|
+
}
|
|
173
|
+
|
|
174
|
+
static void Queue_WriteBuffer(const v8::FunctionCallbackInfo<v8::Value>& args)
|
|
175
|
+
{
|
|
176
|
+
v8::Isolate* isolate = args.GetIsolate();
|
|
177
|
+
wgpu::Queue& queue = Unwrap<wgpu::Queue>(args.This());
|
|
178
|
+
|
|
179
|
+
wgpu::Buffer& buffer = Unwrap<wgpu::Buffer>(args[0].As<v8::Object>());
|
|
180
|
+
uint64_t buffer_offset = static_cast<uint64_t>(args[1].As<v8::Number>()->Value());
|
|
181
|
+
|
|
182
|
+
const void* data = nullptr;
|
|
183
|
+
size_t length = 0;
|
|
184
|
+
if (!CopyBytesFrom(args[2], &data, &length)) {
|
|
185
|
+
v8util::ThrowTypeError(isolate, "writeBuffer: data must be ArrayBuffer(View)");
|
|
186
|
+
return;
|
|
187
|
+
}
|
|
188
|
+
// 任意の dataOffset/size (要素数ではなくバイト) — 簡略化のため未対応時は全体
|
|
189
|
+
uint64_t data_offset = args.Length() > 3 && args[3]->IsNumber()
|
|
190
|
+
? static_cast<uint64_t>(args[3].As<v8::Number>()->Value()) : 0;
|
|
191
|
+
size_t write_size = args.Length() > 4 && args[4]->IsNumber()
|
|
192
|
+
? static_cast<size_t>(args[4].As<v8::Number>()->Value())
|
|
193
|
+
: (length - data_offset);
|
|
194
|
+
|
|
195
|
+
queue.WriteBuffer(buffer, buffer_offset,
|
|
196
|
+
static_cast<const uint8_t*>(data) + data_offset, write_size);
|
|
197
|
+
}
|
|
198
|
+
|
|
199
|
+
static wgpu::Extent3D ParseExtent(v8::Isolate* isolate, v8::Local<v8::Value> value)
|
|
200
|
+
{
|
|
201
|
+
wgpu::Extent3D extent = {1, 1, 1};
|
|
202
|
+
if (value->IsArray()) {
|
|
203
|
+
auto arr = value.As<v8::Array>();
|
|
204
|
+
v8::Local<v8::Context> ctx = isolate->GetCurrentContext();
|
|
205
|
+
auto get = [&](uint32_t i, uint32_t fb) -> uint32_t {
|
|
206
|
+
v8::Local<v8::Value> v;
|
|
207
|
+
return (i < arr->Length() && arr->Get(ctx, i).ToLocal(&v) && v->IsNumber())
|
|
208
|
+
? static_cast<uint32_t>(v.As<v8::Number>()->Value()) : fb;
|
|
209
|
+
};
|
|
210
|
+
extent.width = get(0, 1);
|
|
211
|
+
extent.height = get(1, 1);
|
|
212
|
+
extent.depthOrArrayLayers = get(2, 1);
|
|
213
|
+
} else if (value->IsObject()) {
|
|
214
|
+
auto o = value.As<v8::Object>();
|
|
215
|
+
extent.width = U32(isolate, o, "width", 1);
|
|
216
|
+
extent.height = U32(isolate, o, "height", 1);
|
|
217
|
+
extent.depthOrArrayLayers = U32(isolate, o, "depthOrArrayLayers", 1);
|
|
218
|
+
}
|
|
219
|
+
return extent;
|
|
220
|
+
}
|
|
221
|
+
|
|
222
|
+
static void Queue_WriteTexture(const v8::FunctionCallbackInfo<v8::Value>& args)
|
|
223
|
+
{
|
|
224
|
+
v8::Isolate* isolate = args.GetIsolate();
|
|
225
|
+
wgpu::Queue& queue = Unwrap<wgpu::Queue>(args.This());
|
|
226
|
+
|
|
227
|
+
// destination: { texture, mipLevel?, origin? }
|
|
228
|
+
v8::Local<v8::Object> dest = args[0].As<v8::Object>();
|
|
229
|
+
wgpu::TexelCopyTextureInfo copy = {};
|
|
230
|
+
copy.texture = Unwrap<wgpu::Texture>(Prop(isolate, dest, "texture").As<v8::Object>());
|
|
231
|
+
copy.mipLevel = U32(isolate, dest, "mipLevel", 0);
|
|
232
|
+
|
|
233
|
+
const void* data = nullptr;
|
|
234
|
+
size_t length = 0;
|
|
235
|
+
CopyBytesFrom(args[1], &data, &length);
|
|
236
|
+
|
|
237
|
+
// dataLayout: { offset?, bytesPerRow, rowsPerImage? }
|
|
238
|
+
v8::Local<v8::Object> layout = args[2].As<v8::Object>();
|
|
239
|
+
wgpu::TexelCopyBufferLayout data_layout = {};
|
|
240
|
+
data_layout.offset = U64(isolate, layout, "offset", 0);
|
|
241
|
+
data_layout.bytesPerRow = U32(isolate, layout, "bytesPerRow", 0);
|
|
242
|
+
data_layout.rowsPerImage = U32(isolate, layout, "rowsPerImage", wgpu::kCopyStrideUndefined);
|
|
243
|
+
|
|
244
|
+
wgpu::Extent3D size = ParseExtent(isolate, args[3]);
|
|
245
|
+
|
|
246
|
+
queue.WriteTexture(©, data, length, &data_layout, &size);
|
|
247
|
+
}
|
|
248
|
+
|
|
249
|
+
// queue.copyExternalImageToTexture(source, dest, copySize)
|
|
250
|
+
// source={source: ImageBitmap|canvas, flipY}, dest={texture, premultipliedAlpha, origin?}
|
|
251
|
+
// Dawn の対応 API を使わず、ソースの RGBA を writeTexture で転送する(flipY/premultiply をCPU適用)。
|
|
252
|
+
static void Queue_CopyExternalImageToTexture(const v8::FunctionCallbackInfo<v8::Value>& args)
|
|
253
|
+
{
|
|
254
|
+
v8::Isolate* isolate = args.GetIsolate();
|
|
255
|
+
wgpu::Queue& queue = Unwrap<wgpu::Queue>(args.This());
|
|
256
|
+
|
|
257
|
+
v8::Local<v8::Object> src = args[0].As<v8::Object>();
|
|
258
|
+
v8::Local<v8::Object> dst = args[1].As<v8::Object>();
|
|
259
|
+
|
|
260
|
+
const uint8_t* rgba = nullptr;
|
|
261
|
+
uint32_t sw = 0, sh = 0;
|
|
262
|
+
if (!GetImageSourcePixels(isolate, Prop(isolate, src, "source"), &rgba, &sw, &sh) || !rgba) {
|
|
263
|
+
return;
|
|
264
|
+
}
|
|
265
|
+
const bool flip_y = Bool(isolate, src, "flipY", false);
|
|
266
|
+
const bool premultiply = Bool(isolate, dst, "premultipliedAlpha", false);
|
|
267
|
+
|
|
268
|
+
wgpu::Extent3D size = ParseExtent(isolate, args[2]);
|
|
269
|
+
const uint32_t w = size.width ? size.width : sw;
|
|
270
|
+
const uint32_t h = size.height ? size.height : sh;
|
|
271
|
+
|
|
272
|
+
// flipY / premultiply を適用したコピーを作る
|
|
273
|
+
std::vector<uint8_t> buffer(static_cast<size_t>(w) * h * 4);
|
|
274
|
+
for (uint32_t y = 0; y < h; ++y) {
|
|
275
|
+
const uint32_t sy = flip_y ? (h - 1 - y) : y;
|
|
276
|
+
for (uint32_t x = 0; x < w; ++x) {
|
|
277
|
+
const uint8_t* s = &rgba[(static_cast<size_t>(std::min(sy, sh - 1)) * sw + std::min(x, sw - 1)) * 4];
|
|
278
|
+
uint8_t* d = &buffer[(static_cast<size_t>(y) * w + x) * 4];
|
|
279
|
+
if (premultiply) {
|
|
280
|
+
const double a = s[3] / 255.0;
|
|
281
|
+
d[0] = static_cast<uint8_t>(s[0] * a);
|
|
282
|
+
d[1] = static_cast<uint8_t>(s[1] * a);
|
|
283
|
+
d[2] = static_cast<uint8_t>(s[2] * a);
|
|
284
|
+
} else {
|
|
285
|
+
d[0] = s[0]; d[1] = s[1]; d[2] = s[2];
|
|
286
|
+
}
|
|
287
|
+
d[3] = s[3];
|
|
288
|
+
}
|
|
289
|
+
}
|
|
290
|
+
|
|
291
|
+
wgpu::TexelCopyTextureInfo copy = {};
|
|
292
|
+
copy.texture = Unwrap<wgpu::Texture>(Prop(isolate, dst, "texture").As<v8::Object>());
|
|
293
|
+
wgpu::TexelCopyBufferLayout layout = {};
|
|
294
|
+
layout.bytesPerRow = w * 4;
|
|
295
|
+
layout.rowsPerImage = h;
|
|
296
|
+
wgpu::Extent3D extent = { w, h, 1 };
|
|
297
|
+
queue.WriteTexture(©, buffer.data(), buffer.size(), &layout, &extent);
|
|
298
|
+
}
|
|
299
|
+
|
|
300
|
+
static void Queue_Submit(const v8::FunctionCallbackInfo<v8::Value>& args)
|
|
301
|
+
{
|
|
302
|
+
v8::Isolate* isolate = args.GetIsolate();
|
|
303
|
+
wgpu::Queue& queue = Unwrap<wgpu::Queue>(args.This());
|
|
304
|
+
|
|
305
|
+
std::vector<wgpu::CommandBuffer> buffers;
|
|
306
|
+
if (args.Length() > 0 && args[0]->IsArray()) {
|
|
307
|
+
auto arr = args[0].As<v8::Array>();
|
|
308
|
+
v8::Local<v8::Context> ctx = isolate->GetCurrentContext();
|
|
309
|
+
for (uint32_t i = 0; i < arr->Length(); ++i) {
|
|
310
|
+
v8::Local<v8::Value> v;
|
|
311
|
+
if (arr->Get(ctx, i).ToLocal(&v) && v->IsObject()) {
|
|
312
|
+
buffers.push_back(Unwrap<wgpu::CommandBuffer>(v.As<v8::Object>()));
|
|
313
|
+
}
|
|
314
|
+
}
|
|
315
|
+
}
|
|
316
|
+
queue.Submit(buffers.size(), buffers.data());
|
|
317
|
+
}
|
|
318
|
+
|
|
319
|
+
// ---------------------------------------------------------------------------
|
|
320
|
+
// GPURenderPassEncoder
|
|
321
|
+
// ---------------------------------------------------------------------------
|
|
322
|
+
static void Pass_SetPipeline(const v8::FunctionCallbackInfo<v8::Value>& args)
|
|
323
|
+
{
|
|
324
|
+
Unwrap<wgpu::RenderPassEncoder>(args.This()).SetPipeline(
|
|
325
|
+
Unwrap<wgpu::RenderPipeline>(args[0].As<v8::Object>()));
|
|
326
|
+
}
|
|
327
|
+
|
|
328
|
+
static void Pass_SetBindGroup(const v8::FunctionCallbackInfo<v8::Value>& args)
|
|
329
|
+
{
|
|
330
|
+
v8::Isolate* isolate = args.GetIsolate();
|
|
331
|
+
auto& pass = Unwrap<wgpu::RenderPassEncoder>(args.This());
|
|
332
|
+
uint32_t index = static_cast<uint32_t>(args[0].As<v8::Number>()->Value());
|
|
333
|
+
if (args.Length() < 2 || !args[1]->IsObject()) {
|
|
334
|
+
pass.SetBindGroup(index, nullptr);
|
|
335
|
+
return;
|
|
336
|
+
}
|
|
337
|
+
auto& group = Unwrap<wgpu::BindGroup>(args[1].As<v8::Object>());
|
|
338
|
+
|
|
339
|
+
// dynamicOffsets: hasDynamicOffset=true のレイアウトを使う塗り(fill_dynamic)で必須。
|
|
340
|
+
// 3引数目に Array<number> / Uint32Array で渡る。
|
|
341
|
+
std::vector<uint32_t> offsets;
|
|
342
|
+
if (args.Length() > 2 && !args[2]->IsNullOrUndefined()) {
|
|
343
|
+
v8::Local<v8::Context> ctx = isolate->GetCurrentContext();
|
|
344
|
+
if (args[2]->IsArray()) {
|
|
345
|
+
auto arr = args[2].As<v8::Array>();
|
|
346
|
+
offsets.reserve(arr->Length());
|
|
347
|
+
for (uint32_t i = 0; i < arr->Length(); ++i) {
|
|
348
|
+
v8::Local<v8::Value> v;
|
|
349
|
+
if (arr->Get(ctx, i).ToLocal(&v) && v->IsNumber())
|
|
350
|
+
offsets.push_back(static_cast<uint32_t>(v.As<v8::Number>()->Value()));
|
|
351
|
+
}
|
|
352
|
+
} else if (args[2]->IsUint32Array()) {
|
|
353
|
+
auto ta = args[2].As<v8::Uint32Array>();
|
|
354
|
+
offsets.resize(ta->Length());
|
|
355
|
+
ta->CopyContents(offsets.data(), offsets.size() * sizeof(uint32_t));
|
|
356
|
+
}
|
|
357
|
+
}
|
|
358
|
+
pass.SetBindGroup(index, group,
|
|
359
|
+
static_cast<uint32_t>(offsets.size()),
|
|
360
|
+
offsets.empty() ? nullptr : offsets.data());
|
|
361
|
+
}
|
|
362
|
+
|
|
363
|
+
static void Pass_SetStencilReference(const v8::FunctionCallbackInfo<v8::Value>& args)
|
|
364
|
+
{
|
|
365
|
+
auto& pass = Unwrap<wgpu::RenderPassEncoder>(args.This());
|
|
366
|
+
uint32_t reference = (args.Length() > 0 && args[0]->IsNumber())
|
|
367
|
+
? static_cast<uint32_t>(args[0].As<v8::Number>()->Value()) : 0;
|
|
368
|
+
pass.SetStencilReference(reference);
|
|
369
|
+
}
|
|
370
|
+
|
|
371
|
+
static void Pass_SetBlendConstant(const v8::FunctionCallbackInfo<v8::Value>& args)
|
|
372
|
+
{
|
|
373
|
+
v8::Isolate* isolate = args.GetIsolate();
|
|
374
|
+
auto& pass = Unwrap<wgpu::RenderPassEncoder>(args.This());
|
|
375
|
+
wgpu::Color color = {};
|
|
376
|
+
if (args.Length() > 0 && args[0]->IsObject()) {
|
|
377
|
+
auto o = args[0].As<v8::Object>();
|
|
378
|
+
color = { F64(isolate, o, "r"), F64(isolate, o, "g"),
|
|
379
|
+
F64(isolate, o, "b"), F64(isolate, o, "a") };
|
|
380
|
+
} else if (args.Length() > 0 && args[0]->IsArray()) {
|
|
381
|
+
v8::Local<v8::Context> ctx = isolate->GetCurrentContext();
|
|
382
|
+
auto c = args[0].As<v8::Array>();
|
|
383
|
+
auto g = [&](uint32_t k) { v8::Local<v8::Value> x;
|
|
384
|
+
return (c->Get(ctx, k).ToLocal(&x) && x->IsNumber()) ? x.As<v8::Number>()->Value() : 0.0; };
|
|
385
|
+
color = { g(0), g(1), g(2), g(3) };
|
|
386
|
+
}
|
|
387
|
+
pass.SetBlendConstant(&color);
|
|
388
|
+
}
|
|
389
|
+
|
|
390
|
+
static void Pass_SetVertexBuffer(const v8::FunctionCallbackInfo<v8::Value>& args)
|
|
391
|
+
{
|
|
392
|
+
v8::Isolate* isolate = args.GetIsolate();
|
|
393
|
+
auto& pass = Unwrap<wgpu::RenderPassEncoder>(args.This());
|
|
394
|
+
uint32_t slot = static_cast<uint32_t>(args[0].As<v8::Number>()->Value());
|
|
395
|
+
auto& buffer = Unwrap<wgpu::Buffer>(args[1].As<v8::Object>());
|
|
396
|
+
uint64_t offset = args.Length() > 2 && args[2]->IsNumber()
|
|
397
|
+
? static_cast<uint64_t>(args[2].As<v8::Number>()->Value()) : 0;
|
|
398
|
+
uint64_t size = args.Length() > 3 && args[3]->IsNumber()
|
|
399
|
+
? static_cast<uint64_t>(args[3].As<v8::Number>()->Value()) : wgpu::kWholeSize;
|
|
400
|
+
(void) isolate;
|
|
401
|
+
pass.SetVertexBuffer(slot, buffer, offset, size);
|
|
402
|
+
}
|
|
403
|
+
|
|
404
|
+
static void Pass_SetIndexBuffer(const v8::FunctionCallbackInfo<v8::Value>& args)
|
|
405
|
+
{
|
|
406
|
+
v8::Isolate* isolate = args.GetIsolate();
|
|
407
|
+
auto& pass = Unwrap<wgpu::RenderPassEncoder>(args.This());
|
|
408
|
+
auto& buffer = Unwrap<wgpu::Buffer>(args[0].As<v8::Object>());
|
|
409
|
+
wgpu::IndexFormat format = ToIndexFormat(v8util::ToStdString(isolate, args[1]));
|
|
410
|
+
uint64_t offset = args.Length() > 2 && args[2]->IsNumber()
|
|
411
|
+
? static_cast<uint64_t>(args[2].As<v8::Number>()->Value()) : 0;
|
|
412
|
+
uint64_t size = args.Length() > 3 && args[3]->IsNumber()
|
|
413
|
+
? static_cast<uint64_t>(args[3].As<v8::Number>()->Value()) : wgpu::kWholeSize;
|
|
414
|
+
pass.SetIndexBuffer(buffer, format, offset, size);
|
|
415
|
+
}
|
|
416
|
+
|
|
417
|
+
static void Pass_SetViewport(const v8::FunctionCallbackInfo<v8::Value>& args)
|
|
418
|
+
{
|
|
419
|
+
auto& pass = Unwrap<wgpu::RenderPassEncoder>(args.This());
|
|
420
|
+
auto n = [&](int i) { return static_cast<float>(args[i].As<v8::Number>()->Value()); };
|
|
421
|
+
pass.SetViewport(n(0), n(1), n(2), n(3), n(4), n(5));
|
|
422
|
+
}
|
|
423
|
+
|
|
424
|
+
static void Pass_SetScissorRect(const v8::FunctionCallbackInfo<v8::Value>& args)
|
|
425
|
+
{
|
|
426
|
+
auto& pass = Unwrap<wgpu::RenderPassEncoder>(args.This());
|
|
427
|
+
auto n = [&](int i) { return static_cast<uint32_t>(args[i].As<v8::Number>()->Value()); };
|
|
428
|
+
pass.SetScissorRect(n(0), n(1), n(2), n(3));
|
|
429
|
+
}
|
|
430
|
+
|
|
431
|
+
static void Pass_Draw(const v8::FunctionCallbackInfo<v8::Value>& args)
|
|
432
|
+
{
|
|
433
|
+
auto& pass = Unwrap<wgpu::RenderPassEncoder>(args.This());
|
|
434
|
+
auto n = [&](int i, uint32_t fb) {
|
|
435
|
+
return (i < args.Length() && args[i]->IsNumber())
|
|
436
|
+
? static_cast<uint32_t>(args[i].As<v8::Number>()->Value()) : fb; };
|
|
437
|
+
pass.Draw(n(0, 0), n(1, 1), n(2, 0), n(3, 0));
|
|
438
|
+
}
|
|
439
|
+
|
|
440
|
+
static void Pass_DrawIndexed(const v8::FunctionCallbackInfo<v8::Value>& args)
|
|
441
|
+
{
|
|
442
|
+
auto& pass = Unwrap<wgpu::RenderPassEncoder>(args.This());
|
|
443
|
+
auto n = [&](int i, uint32_t fb) {
|
|
444
|
+
return (i < args.Length() && args[i]->IsNumber())
|
|
445
|
+
? static_cast<uint32_t>(args[i].As<v8::Number>()->Value()) : fb; };
|
|
446
|
+
pass.DrawIndexed(n(0, 0), n(1, 1), n(2, 0), n(3, 0), n(4, 0));
|
|
447
|
+
}
|
|
448
|
+
|
|
449
|
+
static void Pass_DrawIndirect(const v8::FunctionCallbackInfo<v8::Value>& args)
|
|
450
|
+
{
|
|
451
|
+
auto& pass = Unwrap<wgpu::RenderPassEncoder>(args.This());
|
|
452
|
+
auto& buffer = Unwrap<wgpu::Buffer>(args[0].As<v8::Object>());
|
|
453
|
+
uint64_t offset = args.Length() > 1 && args[1]->IsNumber()
|
|
454
|
+
? static_cast<uint64_t>(args[1].As<v8::Number>()->Value()) : 0;
|
|
455
|
+
pass.DrawIndirect(buffer, offset);
|
|
456
|
+
}
|
|
457
|
+
|
|
458
|
+
static void Pass_End(const v8::FunctionCallbackInfo<v8::Value>& args)
|
|
459
|
+
{
|
|
460
|
+
Unwrap<wgpu::RenderPassEncoder>(args.This()).End();
|
|
461
|
+
}
|
|
462
|
+
|
|
463
|
+
static v8::Local<v8::Object> WrapRenderPass(v8::Isolate* isolate, wgpu::RenderPassEncoder pass)
|
|
464
|
+
{
|
|
465
|
+
v8::Local<v8::Object> obj = WrapWith(isolate, Tmpl(isolate).renderPass, std::move(pass));
|
|
466
|
+
SetMethod(isolate, obj, "setPipeline", Pass_SetPipeline);
|
|
467
|
+
SetMethod(isolate, obj, "setBindGroup", Pass_SetBindGroup);
|
|
468
|
+
SetMethod(isolate, obj, "setVertexBuffer", Pass_SetVertexBuffer);
|
|
469
|
+
SetMethod(isolate, obj, "setIndexBuffer", Pass_SetIndexBuffer);
|
|
470
|
+
SetMethod(isolate, obj, "setViewport", Pass_SetViewport);
|
|
471
|
+
SetMethod(isolate, obj, "setScissorRect", Pass_SetScissorRect);
|
|
472
|
+
SetMethod(isolate, obj, "setStencilReference", Pass_SetStencilReference);
|
|
473
|
+
SetMethod(isolate, obj, "setBlendConstant", Pass_SetBlendConstant);
|
|
474
|
+
SetMethod(isolate, obj, "draw", Pass_Draw);
|
|
475
|
+
SetMethod(isolate, obj, "drawIndexed", Pass_DrawIndexed);
|
|
476
|
+
SetMethod(isolate, obj, "drawIndirect", Pass_DrawIndirect);
|
|
477
|
+
SetMethod(isolate, obj, "end", Pass_End);
|
|
478
|
+
return obj;
|
|
479
|
+
}
|
|
480
|
+
|
|
481
|
+
// ---------------------------------------------------------------------------
|
|
482
|
+
// GPUCommandEncoder
|
|
483
|
+
// ---------------------------------------------------------------------------
|
|
484
|
+
static void Encoder_BeginRenderPass(const v8::FunctionCallbackInfo<v8::Value>& args)
|
|
485
|
+
{
|
|
486
|
+
v8::Isolate* isolate = args.GetIsolate();
|
|
487
|
+
v8::Local<v8::Context> ctx = isolate->GetCurrentContext();
|
|
488
|
+
auto& encoder = Unwrap<wgpu::CommandEncoder>(args.This());
|
|
489
|
+
v8::Local<v8::Object> desc = args[0].As<v8::Object>();
|
|
490
|
+
|
|
491
|
+
std::vector<wgpu::RenderPassColorAttachment> color_attachments;
|
|
492
|
+
v8::Local<v8::Value> ca = Prop(isolate, desc, "colorAttachments");
|
|
493
|
+
if (ca->IsArray()) {
|
|
494
|
+
auto arr = ca.As<v8::Array>();
|
|
495
|
+
for (uint32_t i = 0; i < arr->Length(); ++i) {
|
|
496
|
+
v8::Local<v8::Value> v;
|
|
497
|
+
if (!arr->Get(ctx, i).ToLocal(&v) || !v->IsObject()) continue;
|
|
498
|
+
auto o = v.As<v8::Object>();
|
|
499
|
+
wgpu::RenderPassColorAttachment att = {};
|
|
500
|
+
att.view = Unwrap<wgpu::TextureView>(Prop(isolate, o, "view").As<v8::Object>());
|
|
501
|
+
att.loadOp = ToLoadOp(webgpu::Str(isolate, o, "loadOp"));
|
|
502
|
+
att.storeOp = ToStoreOp(webgpu::Str(isolate, o, "storeOp"));
|
|
503
|
+
att.depthSlice = wgpu::kDepthSliceUndefined;
|
|
504
|
+
v8::Local<v8::Value> cv = Prop(isolate, o, "clearValue");
|
|
505
|
+
if (cv->IsArray()) {
|
|
506
|
+
auto c = cv.As<v8::Array>();
|
|
507
|
+
auto g = [&](uint32_t k) { v8::Local<v8::Value> x;
|
|
508
|
+
return (c->Get(ctx, k).ToLocal(&x) && x->IsNumber()) ? x.As<v8::Number>()->Value() : 0.0; };
|
|
509
|
+
att.clearValue = { g(0), g(1), g(2), g(3) };
|
|
510
|
+
} else if (cv->IsObject()) {
|
|
511
|
+
auto c = cv.As<v8::Object>();
|
|
512
|
+
att.clearValue = { F64(isolate, c, "r"), F64(isolate, c, "g"),
|
|
513
|
+
F64(isolate, c, "b"), F64(isolate, c, "a") };
|
|
514
|
+
}
|
|
515
|
+
color_attachments.push_back(att);
|
|
516
|
+
}
|
|
517
|
+
}
|
|
518
|
+
|
|
519
|
+
wgpu::RenderPassDescriptor pass_desc = {};
|
|
520
|
+
pass_desc.colorAttachmentCount = color_attachments.size();
|
|
521
|
+
pass_desc.colorAttachments = color_attachments.data();
|
|
522
|
+
|
|
523
|
+
// depthStencilAttachment
|
|
524
|
+
wgpu::RenderPassDepthStencilAttachment depth = {};
|
|
525
|
+
v8::Local<v8::Value> ds = Prop(isolate, desc, "depthStencilAttachment");
|
|
526
|
+
if (ds->IsObject()) {
|
|
527
|
+
auto o = ds.As<v8::Object>();
|
|
528
|
+
depth.view = Unwrap<wgpu::TextureView>(Prop(isolate, o, "view").As<v8::Object>());
|
|
529
|
+
if (HasProp(isolate, o, "depthLoadOp")) {
|
|
530
|
+
depth.depthLoadOp = ToLoadOp(webgpu::Str(isolate, o, "depthLoadOp"));
|
|
531
|
+
depth.depthStoreOp = ToStoreOp(webgpu::Str(isolate, o, "depthStoreOp"));
|
|
532
|
+
depth.depthClearValue = static_cast<float>(F64(isolate, o, "depthClearValue", 1.0));
|
|
533
|
+
}
|
|
534
|
+
// stencil アスペクト (マスク描画で使用)
|
|
535
|
+
if (HasProp(isolate, o, "stencilLoadOp")) {
|
|
536
|
+
depth.stencilLoadOp = ToLoadOp(webgpu::Str(isolate, o, "stencilLoadOp"));
|
|
537
|
+
depth.stencilStoreOp = ToStoreOp(webgpu::Str(isolate, o, "stencilStoreOp"));
|
|
538
|
+
depth.stencilClearValue = U32(isolate, o, "stencilClearValue", 0);
|
|
539
|
+
}
|
|
540
|
+
if (Bool(isolate, o, "depthReadOnly", false))
|
|
541
|
+
depth.depthReadOnly = true;
|
|
542
|
+
if (Bool(isolate, o, "stencilReadOnly", false))
|
|
543
|
+
depth.stencilReadOnly = true;
|
|
544
|
+
pass_desc.depthStencilAttachment = &depth;
|
|
545
|
+
}
|
|
546
|
+
|
|
547
|
+
args.GetReturnValue().Set(
|
|
548
|
+
WrapRenderPass(isolate, encoder.BeginRenderPass(&pass_desc)));
|
|
549
|
+
}
|
|
550
|
+
|
|
551
|
+
static void Encoder_Finish(const v8::FunctionCallbackInfo<v8::Value>& args)
|
|
552
|
+
{
|
|
553
|
+
v8::Isolate* isolate = args.GetIsolate();
|
|
554
|
+
args.GetReturnValue().Set(
|
|
555
|
+
WrapWith(isolate, Tmpl(isolate).commandBuffer,
|
|
556
|
+
Unwrap<wgpu::CommandEncoder>(args.This()).Finish()));
|
|
557
|
+
}
|
|
558
|
+
|
|
559
|
+
static void Encoder_CopyBufferToBuffer(const v8::FunctionCallbackInfo<v8::Value>& args)
|
|
560
|
+
{
|
|
561
|
+
auto& encoder = Unwrap<wgpu::CommandEncoder>(args.This());
|
|
562
|
+
auto& src = Unwrap<wgpu::Buffer>(args[0].As<v8::Object>());
|
|
563
|
+
uint64_t src_off = static_cast<uint64_t>(args[1].As<v8::Number>()->Value());
|
|
564
|
+
auto& dst = Unwrap<wgpu::Buffer>(args[2].As<v8::Object>());
|
|
565
|
+
uint64_t dst_off = static_cast<uint64_t>(args[3].As<v8::Number>()->Value());
|
|
566
|
+
uint64_t size = static_cast<uint64_t>(args[4].As<v8::Number>()->Value());
|
|
567
|
+
encoder.CopyBufferToBuffer(src, src_off, dst, dst_off, size);
|
|
568
|
+
}
|
|
569
|
+
|
|
570
|
+
// {texture, mipLevel?, origin?} を wgpu::TexelCopyTextureInfo へ
|
|
571
|
+
static wgpu::TexelCopyTextureInfo ParseTexelCopyTexture(v8::Isolate* isolate, v8::Local<v8::Object> o)
|
|
572
|
+
{
|
|
573
|
+
wgpu::TexelCopyTextureInfo info = {};
|
|
574
|
+
info.texture = Unwrap<wgpu::Texture>(Prop(isolate, o, "texture").As<v8::Object>());
|
|
575
|
+
info.mipLevel = U32(isolate, o, "mipLevel", 0);
|
|
576
|
+
v8::Local<v8::Value> origin = Prop(isolate, o, "origin");
|
|
577
|
+
if (origin->IsObject() || origin->IsArray()) {
|
|
578
|
+
wgpu::Extent3D e = ParseExtent(isolate, origin);
|
|
579
|
+
info.origin = { e.width, e.height, e.depthOrArrayLayers };
|
|
580
|
+
}
|
|
581
|
+
return info;
|
|
582
|
+
}
|
|
583
|
+
|
|
584
|
+
static void Encoder_CopyTextureToTexture(const v8::FunctionCallbackInfo<v8::Value>& args)
|
|
585
|
+
{
|
|
586
|
+
v8::Isolate* isolate = args.GetIsolate();
|
|
587
|
+
auto& encoder = Unwrap<wgpu::CommandEncoder>(args.This());
|
|
588
|
+
wgpu::TexelCopyTextureInfo src = ParseTexelCopyTexture(isolate, args[0].As<v8::Object>());
|
|
589
|
+
wgpu::TexelCopyTextureInfo dst = ParseTexelCopyTexture(isolate, args[1].As<v8::Object>());
|
|
590
|
+
wgpu::Extent3D size = ParseExtent(isolate, args[2]);
|
|
591
|
+
encoder.CopyTextureToTexture(&src, &dst, &size);
|
|
592
|
+
}
|
|
593
|
+
|
|
594
|
+
static void Encoder_CopyTextureToBuffer(const v8::FunctionCallbackInfo<v8::Value>& args)
|
|
595
|
+
{
|
|
596
|
+
v8::Isolate* isolate = args.GetIsolate();
|
|
597
|
+
auto& encoder = Unwrap<wgpu::CommandEncoder>(args.This());
|
|
598
|
+
wgpu::TexelCopyTextureInfo src = ParseTexelCopyTexture(isolate, args[0].As<v8::Object>());
|
|
599
|
+
|
|
600
|
+
v8::Local<v8::Object> d = args[1].As<v8::Object>();
|
|
601
|
+
wgpu::TexelCopyBufferInfo dst = {};
|
|
602
|
+
dst.buffer = Unwrap<wgpu::Buffer>(Prop(isolate, d, "buffer").As<v8::Object>());
|
|
603
|
+
dst.layout.offset = U64(isolate, d, "offset", 0);
|
|
604
|
+
dst.layout.bytesPerRow = U32(isolate, d, "bytesPerRow", 0);
|
|
605
|
+
dst.layout.rowsPerImage = U32(isolate, d, "rowsPerImage", wgpu::kCopyStrideUndefined);
|
|
606
|
+
|
|
607
|
+
wgpu::Extent3D size = ParseExtent(isolate, args[2]);
|
|
608
|
+
encoder.CopyTextureToBuffer(&src, &dst, &size);
|
|
609
|
+
}
|
|
610
|
+
|
|
611
|
+
// ---------------------------------------------------------------------------
|
|
612
|
+
// GPUCanvasContext
|
|
613
|
+
// ---------------------------------------------------------------------------
|
|
614
|
+
static void Ctx_Configure(const v8::FunctionCallbackInfo<v8::Value>& args)
|
|
615
|
+
{
|
|
616
|
+
v8::Isolate* isolate = args.GetIsolate();
|
|
617
|
+
DawnContext* gpu = HostContext::From(isolate)->gpu;
|
|
618
|
+
// device は既に DawnContext が保持。フォーマット/サイズのみ反映する。
|
|
619
|
+
if (args.Length() > 0 && args[0]->IsObject()) {
|
|
620
|
+
// width/height は canvas サイズを使用 (configure の size は任意)
|
|
621
|
+
gpu->Configure(gpu->width(), gpu->height());
|
|
622
|
+
}
|
|
623
|
+
}
|
|
624
|
+
|
|
625
|
+
static void Ctx_GetCurrentTexture(const v8::FunctionCallbackInfo<v8::Value>& args)
|
|
626
|
+
{
|
|
627
|
+
v8::Isolate* isolate = args.GetIsolate();
|
|
628
|
+
DawnContext* gpu = HostContext::From(isolate)->gpu;
|
|
629
|
+
args.GetReturnValue().Set(WrapTexture(isolate, gpu->GetCurrentTexture()));
|
|
630
|
+
}
|
|
631
|
+
|
|
632
|
+
static void Ctx_GetConfiguredFormat(const v8::FunctionCallbackInfo<v8::Value>& args)
|
|
633
|
+
{
|
|
634
|
+
// getPreferredCanvasFormat 相当。DawnContext の surface フォーマットを返す。
|
|
635
|
+
v8::Isolate* isolate = args.GetIsolate();
|
|
636
|
+
DawnContext* gpu = HostContext::From(isolate)->gpu;
|
|
637
|
+
const char* fmt = (gpu->format() == wgpu::TextureFormat::RGBA8Unorm)
|
|
638
|
+
? "rgba8unorm" : "bgra8unorm";
|
|
639
|
+
args.GetReturnValue().Set(v8util::Str(isolate, fmt));
|
|
640
|
+
}
|
|
641
|
+
|
|
642
|
+
// タグ付きラップ (bind group で resource 種別を判定するため)
|
|
643
|
+
static v8::Local<v8::Object> WrapTextureView(v8::Isolate* isolate, wgpu::TextureView view)
|
|
644
|
+
{
|
|
645
|
+
auto obj = WrapWith(isolate, Tmpl(isolate).textureView, std::move(view));
|
|
646
|
+
SetValue(isolate, obj, "__gpuType", Str(isolate, "textureView"));
|
|
647
|
+
return obj;
|
|
648
|
+
}
|
|
649
|
+
|
|
650
|
+
static v8::Local<v8::Object> WrapSampler(v8::Isolate* isolate, wgpu::Sampler sampler)
|
|
651
|
+
{
|
|
652
|
+
auto obj = WrapWith(isolate, Tmpl(isolate).sampler, std::move(sampler));
|
|
653
|
+
SetValue(isolate, obj, "__gpuType", Str(isolate, "sampler"));
|
|
654
|
+
return obj;
|
|
655
|
+
}
|
|
656
|
+
|
|
657
|
+
// ---------------------------------------------------------------------------
|
|
658
|
+
// GPUDevice.createBuffer
|
|
659
|
+
// ---------------------------------------------------------------------------
|
|
660
|
+
static void Device_CreateBuffer(const v8::FunctionCallbackInfo<v8::Value>& args)
|
|
661
|
+
{
|
|
662
|
+
v8::Isolate* isolate = args.GetIsolate();
|
|
663
|
+
auto& device = Unwrap<wgpu::Device>(args.This());
|
|
664
|
+
v8::Local<v8::Object> d = args[0].As<v8::Object>();
|
|
665
|
+
|
|
666
|
+
wgpu::BufferDescriptor desc = {};
|
|
667
|
+
desc.size = U64(isolate, d, "size", 0);
|
|
668
|
+
desc.usage = static_cast<wgpu::BufferUsage>(U32(isolate, d, "usage", 0));
|
|
669
|
+
desc.mappedAtCreation = Bool(isolate, d, "mappedAtCreation", false);
|
|
670
|
+
|
|
671
|
+
args.GetReturnValue().Set(WrapBuffer(isolate, device.CreateBuffer(&desc)));
|
|
672
|
+
}
|
|
673
|
+
|
|
674
|
+
// ---------------------------------------------------------------------------
|
|
675
|
+
// GPUDevice.createTexture
|
|
676
|
+
// ---------------------------------------------------------------------------
|
|
677
|
+
static void Device_CreateTexture(const v8::FunctionCallbackInfo<v8::Value>& args)
|
|
678
|
+
{
|
|
679
|
+
v8::Isolate* isolate = args.GetIsolate();
|
|
680
|
+
auto& device = Unwrap<wgpu::Device>(args.This());
|
|
681
|
+
v8::Local<v8::Object> d = args[0].As<v8::Object>();
|
|
682
|
+
|
|
683
|
+
wgpu::TextureDescriptor desc = {};
|
|
684
|
+
desc.size = ParseExtent(isolate, Prop(isolate, d, "size"));
|
|
685
|
+
desc.format = ToTextureFormat(webgpu::Str(isolate, d, "format"));
|
|
686
|
+
desc.usage = static_cast<wgpu::TextureUsage>(U32(isolate, d, "usage", 0));
|
|
687
|
+
desc.dimension = HasProp(isolate, d, "dimension")
|
|
688
|
+
? ToTextureDimension(webgpu::Str(isolate, d, "dimension"))
|
|
689
|
+
: wgpu::TextureDimension::e2D;
|
|
690
|
+
desc.mipLevelCount = U32(isolate, d, "mipLevelCount", 1);
|
|
691
|
+
desc.sampleCount = U32(isolate, d, "sampleCount", 1);
|
|
692
|
+
|
|
693
|
+
args.GetReturnValue().Set(WrapTexture(isolate, device.CreateTexture(&desc)));
|
|
694
|
+
}
|
|
695
|
+
|
|
696
|
+
// ---------------------------------------------------------------------------
|
|
697
|
+
// GPUDevice.createSampler
|
|
698
|
+
// ---------------------------------------------------------------------------
|
|
699
|
+
static void Device_CreateSampler(const v8::FunctionCallbackInfo<v8::Value>& args)
|
|
700
|
+
{
|
|
701
|
+
v8::Isolate* isolate = args.GetIsolate();
|
|
702
|
+
auto& device = Unwrap<wgpu::Device>(args.This());
|
|
703
|
+
|
|
704
|
+
wgpu::SamplerDescriptor desc = {};
|
|
705
|
+
if (args.Length() > 0 && args[0]->IsObject()) {
|
|
706
|
+
auto d = args[0].As<v8::Object>();
|
|
707
|
+
desc.addressModeU = ToAddressMode(webgpu::Str(isolate, d, "addressModeU"));
|
|
708
|
+
desc.addressModeV = ToAddressMode(webgpu::Str(isolate, d, "addressModeV"));
|
|
709
|
+
desc.addressModeW = ToAddressMode(webgpu::Str(isolate, d, "addressModeW"));
|
|
710
|
+
desc.magFilter = ToFilterMode(webgpu::Str(isolate, d, "magFilter"));
|
|
711
|
+
desc.minFilter = ToFilterMode(webgpu::Str(isolate, d, "minFilter"));
|
|
712
|
+
desc.mipmapFilter = ToMipmapFilterMode(webgpu::Str(isolate, d, "mipmapFilter"));
|
|
713
|
+
if (HasProp(isolate, d, "lodMinClamp")) desc.lodMinClamp = static_cast<float>(F64(isolate, d, "lodMinClamp"));
|
|
714
|
+
if (HasProp(isolate, d, "lodMaxClamp")) desc.lodMaxClamp = static_cast<float>(F64(isolate, d, "lodMaxClamp", 32.f));
|
|
715
|
+
if (HasProp(isolate, d, "maxAnisotropy")) desc.maxAnisotropy = static_cast<uint16_t>(U32(isolate, d, "maxAnisotropy", 1));
|
|
716
|
+
}
|
|
717
|
+
args.GetReturnValue().Set(WrapSampler(isolate, device.CreateSampler(&desc)));
|
|
718
|
+
}
|
|
719
|
+
|
|
720
|
+
// ---------------------------------------------------------------------------
|
|
721
|
+
// GPUDevice.createShaderModule
|
|
722
|
+
// ---------------------------------------------------------------------------
|
|
723
|
+
static void Device_CreateShaderModule(const v8::FunctionCallbackInfo<v8::Value>& args)
|
|
724
|
+
{
|
|
725
|
+
v8::Isolate* isolate = args.GetIsolate();
|
|
726
|
+
auto& device = Unwrap<wgpu::Device>(args.This());
|
|
727
|
+
v8::Local<v8::Object> d = args[0].As<v8::Object>();
|
|
728
|
+
|
|
729
|
+
const std::string code = webgpu::Str(isolate, d, "code");
|
|
730
|
+
|
|
731
|
+
wgpu::ShaderSourceWGSL wgsl = {};
|
|
732
|
+
wgsl.code = wgpu::StringView(code.c_str(), code.size());
|
|
733
|
+
|
|
734
|
+
wgpu::ShaderModuleDescriptor desc = {};
|
|
735
|
+
desc.nextInChain = &wgsl;
|
|
736
|
+
|
|
737
|
+
args.GetReturnValue().Set(
|
|
738
|
+
WrapWith(isolate, Tmpl(isolate).shaderModule, device.CreateShaderModule(&desc)));
|
|
739
|
+
}
|
|
740
|
+
|
|
741
|
+
// ---------------------------------------------------------------------------
|
|
742
|
+
// GPUDevice.createBindGroupLayout
|
|
743
|
+
// ---------------------------------------------------------------------------
|
|
744
|
+
static void Device_CreateBindGroupLayout(const v8::FunctionCallbackInfo<v8::Value>& args)
|
|
745
|
+
{
|
|
746
|
+
v8::Isolate* isolate = args.GetIsolate();
|
|
747
|
+
v8::Local<v8::Context> ctx = isolate->GetCurrentContext();
|
|
748
|
+
auto& device = Unwrap<wgpu::Device>(args.This());
|
|
749
|
+
v8::Local<v8::Object> d = args[0].As<v8::Object>();
|
|
750
|
+
|
|
751
|
+
std::vector<wgpu::BindGroupLayoutEntry> entries;
|
|
752
|
+
v8::Local<v8::Value> ev = Prop(isolate, d, "entries");
|
|
753
|
+
if (ev->IsArray()) {
|
|
754
|
+
auto arr = ev.As<v8::Array>();
|
|
755
|
+
for (uint32_t i = 0; i < arr->Length(); ++i) {
|
|
756
|
+
v8::Local<v8::Value> v;
|
|
757
|
+
if (!arr->Get(ctx, i).ToLocal(&v) || !v->IsObject()) continue;
|
|
758
|
+
auto o = v.As<v8::Object>();
|
|
759
|
+
wgpu::BindGroupLayoutEntry entry = {};
|
|
760
|
+
entry.binding = U32(isolate, o, "binding", 0);
|
|
761
|
+
entry.visibility = static_cast<wgpu::ShaderStage>(U32(isolate, o, "visibility", 0));
|
|
762
|
+
|
|
763
|
+
if (HasProp(isolate, o, "buffer")) {
|
|
764
|
+
auto b = Prop(isolate, o, "buffer").As<v8::Object>();
|
|
765
|
+
entry.buffer.type = ToBufferBindingType(webgpu::Str(isolate, b, "type"));
|
|
766
|
+
entry.buffer.hasDynamicOffset = Bool(isolate, b, "hasDynamicOffset", false);
|
|
767
|
+
entry.buffer.minBindingSize = U64(isolate, b, "minBindingSize", 0);
|
|
768
|
+
} else if (HasProp(isolate, o, "sampler")) {
|
|
769
|
+
auto s = Prop(isolate, o, "sampler").As<v8::Object>();
|
|
770
|
+
entry.sampler.type = ToSamplerBindingType(webgpu::Str(isolate, s, "type"));
|
|
771
|
+
} else if (HasProp(isolate, o, "texture")) {
|
|
772
|
+
auto t = Prop(isolate, o, "texture").As<v8::Object>();
|
|
773
|
+
entry.texture.sampleType = ToTextureSampleType(webgpu::Str(isolate, t, "sampleType"));
|
|
774
|
+
entry.texture.viewDimension = HasProp(isolate, t, "viewDimension")
|
|
775
|
+
? ToTextureViewDimension(webgpu::Str(isolate, t, "viewDimension"))
|
|
776
|
+
: wgpu::TextureViewDimension::e2D;
|
|
777
|
+
entry.texture.multisampled = Bool(isolate, t, "multisampled", false);
|
|
778
|
+
}
|
|
779
|
+
// «EXTEND» storageTexture / externalTexture は必要に応じて追加
|
|
780
|
+
entries.push_back(entry);
|
|
781
|
+
}
|
|
782
|
+
}
|
|
783
|
+
|
|
784
|
+
wgpu::BindGroupLayoutDescriptor desc = {};
|
|
785
|
+
desc.entryCount = entries.size();
|
|
786
|
+
desc.entries = entries.data();
|
|
787
|
+
|
|
788
|
+
args.GetReturnValue().Set(
|
|
789
|
+
WrapWith(isolate, Tmpl(isolate).bindGroupLayout, device.CreateBindGroupLayout(&desc)));
|
|
790
|
+
}
|
|
791
|
+
|
|
792
|
+
// ---------------------------------------------------------------------------
|
|
793
|
+
// GPUDevice.createBindGroup
|
|
794
|
+
// ---------------------------------------------------------------------------
|
|
795
|
+
static void Device_CreateBindGroup(const v8::FunctionCallbackInfo<v8::Value>& args)
|
|
796
|
+
{
|
|
797
|
+
v8::Isolate* isolate = args.GetIsolate();
|
|
798
|
+
v8::Local<v8::Context> ctx = isolate->GetCurrentContext();
|
|
799
|
+
auto& device = Unwrap<wgpu::Device>(args.This());
|
|
800
|
+
v8::Local<v8::Object> d = args[0].As<v8::Object>();
|
|
801
|
+
|
|
802
|
+
std::vector<wgpu::BindGroupEntry> entries;
|
|
803
|
+
v8::Local<v8::Value> ev = Prop(isolate, d, "entries");
|
|
804
|
+
if (ev->IsArray()) {
|
|
805
|
+
auto arr = ev.As<v8::Array>();
|
|
806
|
+
for (uint32_t i = 0; i < arr->Length(); ++i) {
|
|
807
|
+
v8::Local<v8::Value> v;
|
|
808
|
+
if (!arr->Get(ctx, i).ToLocal(&v) || !v->IsObject()) continue;
|
|
809
|
+
auto o = v.As<v8::Object>();
|
|
810
|
+
wgpu::BindGroupEntry entry = {};
|
|
811
|
+
entry.binding = U32(isolate, o, "binding", 0);
|
|
812
|
+
|
|
813
|
+
v8::Local<v8::Value> res = Prop(isolate, o, "resource");
|
|
814
|
+
if (res->IsObject()) {
|
|
815
|
+
auto ro = res.As<v8::Object>();
|
|
816
|
+
if (HasProp(isolate, ro, "buffer")) {
|
|
817
|
+
entry.buffer = Unwrap<wgpu::Buffer>(Prop(isolate, ro, "buffer").As<v8::Object>());
|
|
818
|
+
entry.offset = U64(isolate, ro, "offset", 0);
|
|
819
|
+
if (HasProp(isolate, ro, "size")) entry.size = U64(isolate, ro, "size", 0);
|
|
820
|
+
else entry.size = wgpu::kWholeSize;
|
|
821
|
+
} else {
|
|
822
|
+
const std::string type = webgpu::Str(isolate, ro, "__gpuType");
|
|
823
|
+
if (type == "sampler") {
|
|
824
|
+
entry.sampler = Unwrap<wgpu::Sampler>(ro);
|
|
825
|
+
} else {
|
|
826
|
+
entry.textureView = Unwrap<wgpu::TextureView>(ro);
|
|
827
|
+
}
|
|
828
|
+
}
|
|
829
|
+
}
|
|
830
|
+
entries.push_back(entry);
|
|
831
|
+
}
|
|
832
|
+
}
|
|
833
|
+
|
|
834
|
+
wgpu::BindGroupDescriptor desc = {};
|
|
835
|
+
desc.layout = Unwrap<wgpu::BindGroupLayout>(Prop(isolate, d, "layout").As<v8::Object>());
|
|
836
|
+
desc.entryCount = entries.size();
|
|
837
|
+
desc.entries = entries.data();
|
|
838
|
+
|
|
839
|
+
args.GetReturnValue().Set(
|
|
840
|
+
WrapWith(isolate, Tmpl(isolate).bindGroup, device.CreateBindGroup(&desc)));
|
|
841
|
+
}
|
|
842
|
+
|
|
843
|
+
// ---------------------------------------------------------------------------
|
|
844
|
+
// GPUDevice.createPipelineLayout
|
|
845
|
+
// ---------------------------------------------------------------------------
|
|
846
|
+
static void Device_CreatePipelineLayout(const v8::FunctionCallbackInfo<v8::Value>& args)
|
|
847
|
+
{
|
|
848
|
+
v8::Isolate* isolate = args.GetIsolate();
|
|
849
|
+
v8::Local<v8::Context> ctx = isolate->GetCurrentContext();
|
|
850
|
+
auto& device = Unwrap<wgpu::Device>(args.This());
|
|
851
|
+
v8::Local<v8::Object> d = args[0].As<v8::Object>();
|
|
852
|
+
|
|
853
|
+
std::vector<wgpu::BindGroupLayout> layouts;
|
|
854
|
+
v8::Local<v8::Value> lv = Prop(isolate, d, "bindGroupLayouts");
|
|
855
|
+
if (lv->IsArray()) {
|
|
856
|
+
auto arr = lv.As<v8::Array>();
|
|
857
|
+
for (uint32_t i = 0; i < arr->Length(); ++i) {
|
|
858
|
+
v8::Local<v8::Value> v;
|
|
859
|
+
if (arr->Get(ctx, i).ToLocal(&v) && v->IsObject()) {
|
|
860
|
+
layouts.push_back(Unwrap<wgpu::BindGroupLayout>(v.As<v8::Object>()));
|
|
861
|
+
}
|
|
862
|
+
}
|
|
863
|
+
}
|
|
864
|
+
|
|
865
|
+
wgpu::PipelineLayoutDescriptor desc = {};
|
|
866
|
+
desc.bindGroupLayoutCount = layouts.size();
|
|
867
|
+
desc.bindGroupLayouts = layouts.data();
|
|
868
|
+
|
|
869
|
+
args.GetReturnValue().Set(
|
|
870
|
+
WrapWith(isolate, Tmpl(isolate).pipelineLayout, device.CreatePipelineLayout(&desc)));
|
|
871
|
+
}
|
|
872
|
+
|
|
873
|
+
// ---------------------------------------------------------------------------
|
|
874
|
+
// GPUDevice.createRenderPipeline
|
|
875
|
+
// ---------------------------------------------------------------------------
|
|
876
|
+
// ディスクリプタ内で参照する一時ストレージ (CreateRenderPipeline は同期コピーするため
|
|
877
|
+
// 呼び出しが終わるまでこれらの vector を生存させる)。
|
|
878
|
+
struct RenderPipelineScratch {
|
|
879
|
+
std::vector<std::vector<wgpu::VertexAttribute>> attributes;
|
|
880
|
+
std::vector<wgpu::VertexBufferLayout> vertex_buffers;
|
|
881
|
+
std::vector<wgpu::ColorTargetState> targets;
|
|
882
|
+
std::vector<wgpu::BlendState> blends;
|
|
883
|
+
std::string vs_entry, fs_entry;
|
|
884
|
+
};
|
|
885
|
+
|
|
886
|
+
static void Device_CreateRenderPipeline(const v8::FunctionCallbackInfo<v8::Value>& args)
|
|
887
|
+
{
|
|
888
|
+
v8::Isolate* isolate = args.GetIsolate();
|
|
889
|
+
v8::Local<v8::Context> ctx = isolate->GetCurrentContext();
|
|
890
|
+
auto& device = Unwrap<wgpu::Device>(args.This());
|
|
891
|
+
v8::Local<v8::Object> d = args[0].As<v8::Object>();
|
|
892
|
+
|
|
893
|
+
RenderPipelineScratch scratch;
|
|
894
|
+
wgpu::RenderPipelineDescriptor desc = {};
|
|
895
|
+
|
|
896
|
+
// layout: 'auto' or GPUPipelineLayout
|
|
897
|
+
v8::Local<v8::Value> layout = Prop(isolate, d, "layout");
|
|
898
|
+
if (layout->IsObject()) {
|
|
899
|
+
desc.layout = Unwrap<wgpu::PipelineLayout>(layout.As<v8::Object>());
|
|
900
|
+
} // 'auto' の場合は nullptr のまま
|
|
901
|
+
|
|
902
|
+
// vertex
|
|
903
|
+
v8::Local<v8::Object> vertex = Prop(isolate, d, "vertex").As<v8::Object>();
|
|
904
|
+
desc.vertex.module = Unwrap<wgpu::ShaderModule>(Prop(isolate, vertex, "module").As<v8::Object>());
|
|
905
|
+
scratch.vs_entry = webgpu::Str(isolate, vertex, "entryPoint");
|
|
906
|
+
if (!scratch.vs_entry.empty()) {
|
|
907
|
+
desc.vertex.entryPoint = wgpu::StringView(scratch.vs_entry.c_str(), scratch.vs_entry.size());
|
|
908
|
+
}
|
|
909
|
+
|
|
910
|
+
v8::Local<v8::Value> vbs = Prop(isolate, vertex, "buffers");
|
|
911
|
+
if (vbs->IsArray()) {
|
|
912
|
+
auto arr = vbs.As<v8::Array>();
|
|
913
|
+
for (uint32_t i = 0; i < arr->Length(); ++i) {
|
|
914
|
+
v8::Local<v8::Value> v;
|
|
915
|
+
if (!arr->Get(ctx, i).ToLocal(&v) || !v->IsObject()) continue;
|
|
916
|
+
auto o = v.As<v8::Object>();
|
|
917
|
+
|
|
918
|
+
std::vector<wgpu::VertexAttribute> attrs;
|
|
919
|
+
v8::Local<v8::Value> av = Prop(isolate, o, "attributes");
|
|
920
|
+
if (av->IsArray()) {
|
|
921
|
+
auto aarr = av.As<v8::Array>();
|
|
922
|
+
for (uint32_t j = 0; j < aarr->Length(); ++j) {
|
|
923
|
+
v8::Local<v8::Value> a;
|
|
924
|
+
if (!aarr->Get(ctx, j).ToLocal(&a) || !a->IsObject()) continue;
|
|
925
|
+
auto ao = a.As<v8::Object>();
|
|
926
|
+
wgpu::VertexAttribute attr = {};
|
|
927
|
+
attr.format = ToVertexFormat(webgpu::Str(isolate, ao, "format"));
|
|
928
|
+
attr.offset = U64(isolate, ao, "offset", 0);
|
|
929
|
+
attr.shaderLocation = U32(isolate, ao, "shaderLocation", 0);
|
|
930
|
+
attrs.push_back(attr);
|
|
931
|
+
}
|
|
932
|
+
}
|
|
933
|
+
scratch.attributes.push_back(std::move(attrs));
|
|
934
|
+
|
|
935
|
+
wgpu::VertexBufferLayout vbl = {};
|
|
936
|
+
vbl.arrayStride = U64(isolate, o, "arrayStride", 0);
|
|
937
|
+
vbl.stepMode = HasProp(isolate, o, "stepMode")
|
|
938
|
+
? ToStepMode(webgpu::Str(isolate, o, "stepMode")) : wgpu::VertexStepMode::Vertex;
|
|
939
|
+
vbl.attributeCount = scratch.attributes.back().size();
|
|
940
|
+
vbl.attributes = scratch.attributes.back().data();
|
|
941
|
+
scratch.vertex_buffers.push_back(vbl);
|
|
942
|
+
}
|
|
943
|
+
desc.vertex.bufferCount = scratch.vertex_buffers.size();
|
|
944
|
+
desc.vertex.buffers = scratch.vertex_buffers.data();
|
|
945
|
+
}
|
|
946
|
+
|
|
947
|
+
// primitive
|
|
948
|
+
v8::Local<v8::Value> prim = Prop(isolate, d, "primitive");
|
|
949
|
+
if (prim->IsObject()) {
|
|
950
|
+
auto p = prim.As<v8::Object>();
|
|
951
|
+
desc.primitive.topology = ToTopology(webgpu::Str(isolate, p, "topology"));
|
|
952
|
+
if (HasProp(isolate, p, "stripIndexFormat"))
|
|
953
|
+
desc.primitive.stripIndexFormat = ToIndexFormat(webgpu::Str(isolate, p, "stripIndexFormat"));
|
|
954
|
+
if (HasProp(isolate, p, "frontFace"))
|
|
955
|
+
desc.primitive.frontFace = ToFrontFace(webgpu::Str(isolate, p, "frontFace"));
|
|
956
|
+
if (HasProp(isolate, p, "cullMode"))
|
|
957
|
+
desc.primitive.cullMode = ToCullMode(webgpu::Str(isolate, p, "cullMode"));
|
|
958
|
+
}
|
|
959
|
+
|
|
960
|
+
// depthStencil (マスク処理は stencil8 + stencilFront/Back を使う)
|
|
961
|
+
wgpu::DepthStencilState depth = {};
|
|
962
|
+
v8::Local<v8::Value> dsv = Prop(isolate, d, "depthStencil");
|
|
963
|
+
if (dsv->IsObject()) {
|
|
964
|
+
auto ds = dsv.As<v8::Object>();
|
|
965
|
+
depth.format = ToTextureFormat(webgpu::Str(isolate, ds, "format"));
|
|
966
|
+
|
|
967
|
+
// depth アスペクトを持つフォーマットのときのみ depthWriteEnabled/depthCompare を設定する。
|
|
968
|
+
// stencil8 (depth なし) では両者を未設定(Undefined)のままにしないと検証エラーになる。
|
|
969
|
+
const bool has_depth = depth.format == wgpu::TextureFormat::Depth16Unorm
|
|
970
|
+
|| depth.format == wgpu::TextureFormat::Depth24Plus
|
|
971
|
+
|| depth.format == wgpu::TextureFormat::Depth24PlusStencil8
|
|
972
|
+
|| depth.format == wgpu::TextureFormat::Depth32Float
|
|
973
|
+
|| depth.format == wgpu::TextureFormat::Depth32FloatStencil8;
|
|
974
|
+
if (has_depth) {
|
|
975
|
+
depth.depthWriteEnabled = Bool(isolate, ds, "depthWriteEnabled", false)
|
|
976
|
+
? wgpu::OptionalBool::True : wgpu::OptionalBool::False;
|
|
977
|
+
depth.depthCompare = HasProp(isolate, ds, "depthCompare")
|
|
978
|
+
? ToCompareFunction(webgpu::Str(isolate, ds, "depthCompare"))
|
|
979
|
+
: wgpu::CompareFunction::Always;
|
|
980
|
+
}
|
|
981
|
+
|
|
982
|
+
auto parseFace = [&](const char* key, wgpu::StencilFaceState& face) {
|
|
983
|
+
v8::Local<v8::Value> fv = Prop(isolate, ds, key);
|
|
984
|
+
if (!fv->IsObject()) return;
|
|
985
|
+
auto f = fv.As<v8::Object>();
|
|
986
|
+
if (HasProp(isolate, f, "compare"))
|
|
987
|
+
face.compare = ToCompareFunction(webgpu::Str(isolate, f, "compare"));
|
|
988
|
+
if (HasProp(isolate, f, "failOp"))
|
|
989
|
+
face.failOp = ToStencilOperation(webgpu::Str(isolate, f, "failOp"));
|
|
990
|
+
if (HasProp(isolate, f, "depthFailOp"))
|
|
991
|
+
face.depthFailOp = ToStencilOperation(webgpu::Str(isolate, f, "depthFailOp"));
|
|
992
|
+
if (HasProp(isolate, f, "passOp"))
|
|
993
|
+
face.passOp = ToStencilOperation(webgpu::Str(isolate, f, "passOp"));
|
|
994
|
+
};
|
|
995
|
+
parseFace("stencilFront", depth.stencilFront);
|
|
996
|
+
parseFace("stencilBack", depth.stencilBack);
|
|
997
|
+
|
|
998
|
+
if (HasProp(isolate, ds, "stencilReadMask"))
|
|
999
|
+
depth.stencilReadMask = U32(isolate, ds, "stencilReadMask", 0xFFFFFFFF);
|
|
1000
|
+
if (HasProp(isolate, ds, "stencilWriteMask"))
|
|
1001
|
+
depth.stencilWriteMask = U32(isolate, ds, "stencilWriteMask", 0xFFFFFFFF);
|
|
1002
|
+
|
|
1003
|
+
desc.depthStencil = &depth;
|
|
1004
|
+
}
|
|
1005
|
+
|
|
1006
|
+
// multisample
|
|
1007
|
+
v8::Local<v8::Value> ms = Prop(isolate, d, "multisample");
|
|
1008
|
+
if (ms->IsObject()) {
|
|
1009
|
+
auto m = ms.As<v8::Object>();
|
|
1010
|
+
desc.multisample.count = U32(isolate, m, "count", 1);
|
|
1011
|
+
}
|
|
1012
|
+
|
|
1013
|
+
// fragment
|
|
1014
|
+
wgpu::FragmentState fragment = {};
|
|
1015
|
+
v8::Local<v8::Value> fv = Prop(isolate, d, "fragment");
|
|
1016
|
+
if (fv->IsObject()) {
|
|
1017
|
+
auto f = fv.As<v8::Object>();
|
|
1018
|
+
fragment.module = Unwrap<wgpu::ShaderModule>(Prop(isolate, f, "module").As<v8::Object>());
|
|
1019
|
+
scratch.fs_entry = webgpu::Str(isolate, f, "entryPoint");
|
|
1020
|
+
if (!scratch.fs_entry.empty()) {
|
|
1021
|
+
fragment.entryPoint = wgpu::StringView(scratch.fs_entry.c_str(), scratch.fs_entry.size());
|
|
1022
|
+
}
|
|
1023
|
+
|
|
1024
|
+
v8::Local<v8::Value> tv = Prop(isolate, f, "targets");
|
|
1025
|
+
if (tv->IsArray()) {
|
|
1026
|
+
auto arr = tv.As<v8::Array>();
|
|
1027
|
+
scratch.blends.resize(arr->Length());
|
|
1028
|
+
for (uint32_t i = 0; i < arr->Length(); ++i) {
|
|
1029
|
+
v8::Local<v8::Value> v;
|
|
1030
|
+
if (!arr->Get(ctx, i).ToLocal(&v) || !v->IsObject()) { scratch.targets.push_back({}); continue; }
|
|
1031
|
+
auto o = v.As<v8::Object>();
|
|
1032
|
+
wgpu::ColorTargetState target = {};
|
|
1033
|
+
target.format = ToTextureFormat(webgpu::Str(isolate, o, "format"));
|
|
1034
|
+
if (HasProp(isolate, o, "writeMask"))
|
|
1035
|
+
target.writeMask = static_cast<wgpu::ColorWriteMask>(U32(isolate, o, "writeMask", 0xF));
|
|
1036
|
+
|
|
1037
|
+
v8::Local<v8::Value> bv = Prop(isolate, o, "blend");
|
|
1038
|
+
if (bv->IsObject()) {
|
|
1039
|
+
auto b = bv.As<v8::Object>();
|
|
1040
|
+
wgpu::BlendState& blend = scratch.blends[i];
|
|
1041
|
+
auto color = Prop(isolate, b, "color").As<v8::Object>();
|
|
1042
|
+
auto alpha = Prop(isolate, b, "alpha").As<v8::Object>();
|
|
1043
|
+
blend.color.srcFactor = ToBlendFactor(webgpu::Str(isolate, color, "srcFactor"));
|
|
1044
|
+
blend.color.dstFactor = ToBlendFactor(webgpu::Str(isolate, color, "dstFactor"));
|
|
1045
|
+
blend.color.operation = ToBlendOperation(webgpu::Str(isolate, color, "operation"));
|
|
1046
|
+
blend.alpha.srcFactor = ToBlendFactor(webgpu::Str(isolate, alpha, "srcFactor"));
|
|
1047
|
+
blend.alpha.dstFactor = ToBlendFactor(webgpu::Str(isolate, alpha, "dstFactor"));
|
|
1048
|
+
blend.alpha.operation = ToBlendOperation(webgpu::Str(isolate, alpha, "operation"));
|
|
1049
|
+
target.blend = &blend;
|
|
1050
|
+
}
|
|
1051
|
+
scratch.targets.push_back(target);
|
|
1052
|
+
}
|
|
1053
|
+
fragment.targetCount = scratch.targets.size();
|
|
1054
|
+
fragment.targets = scratch.targets.data();
|
|
1055
|
+
}
|
|
1056
|
+
desc.fragment = &fragment;
|
|
1057
|
+
}
|
|
1058
|
+
|
|
1059
|
+
args.GetReturnValue().Set(WrapPipeline(isolate, device.CreateRenderPipeline(&desc)));
|
|
1060
|
+
}
|
|
1061
|
+
|
|
1062
|
+
static void Device_CreateCommandEncoder(const v8::FunctionCallbackInfo<v8::Value>& args)
|
|
1063
|
+
{
|
|
1064
|
+
v8::Isolate* isolate = args.GetIsolate();
|
|
1065
|
+
auto& device = Unwrap<wgpu::Device>(args.This());
|
|
1066
|
+
args.GetReturnValue().Set(WrapEncoder(isolate, device.CreateCommandEncoder()));
|
|
1067
|
+
}
|
|
1068
|
+
|
|
1069
|
+
static void Pipeline_GetBindGroupLayout(const v8::FunctionCallbackInfo<v8::Value>& args)
|
|
1070
|
+
{
|
|
1071
|
+
v8::Isolate* isolate = args.GetIsolate();
|
|
1072
|
+
auto& pipeline = Unwrap<wgpu::RenderPipeline>(args.This());
|
|
1073
|
+
uint32_t index = args.Length() > 0 && args[0]->IsNumber()
|
|
1074
|
+
? static_cast<uint32_t>(args[0].As<v8::Number>()->Value()) : 0;
|
|
1075
|
+
args.GetReturnValue().Set(
|
|
1076
|
+
WrapWith(isolate, Tmpl(isolate).bindGroupLayout, pipeline.GetBindGroupLayout(index)));
|
|
1077
|
+
}
|
|
1078
|
+
|
|
1079
|
+
// ---------------------------------------------------------------------------
|
|
1080
|
+
// メソッド付与済みラップ (前方宣言の定義)
|
|
1081
|
+
// ---------------------------------------------------------------------------
|
|
1082
|
+
static v8::Local<v8::Object> WrapBuffer(v8::Isolate* isolate, wgpu::Buffer buffer)
|
|
1083
|
+
{
|
|
1084
|
+
auto obj = WrapWith(isolate, Tmpl(isolate).buffer, std::move(buffer));
|
|
1085
|
+
SetValue(isolate, obj, "size", v8::Number::New(isolate,
|
|
1086
|
+
static_cast<double>(Unwrap<wgpu::Buffer>(obj).GetSize())));
|
|
1087
|
+
SetMethod(isolate, obj, "getMappedRange", Buffer_GetMappedRange);
|
|
1088
|
+
SetMethod(isolate, obj, "unmap", Buffer_Unmap);
|
|
1089
|
+
SetMethod(isolate, obj, "mapAsync", Buffer_MapAsync);
|
|
1090
|
+
SetMethod(isolate, obj, "destroy", Buffer_Destroy);
|
|
1091
|
+
return obj;
|
|
1092
|
+
}
|
|
1093
|
+
|
|
1094
|
+
static v8::Local<v8::Object> WrapTexture(v8::Isolate* isolate, wgpu::Texture texture)
|
|
1095
|
+
{
|
|
1096
|
+
auto obj = WrapWith(isolate, Tmpl(isolate).texture, std::move(texture));
|
|
1097
|
+
auto& t = Unwrap<wgpu::Texture>(obj);
|
|
1098
|
+
SetValue(isolate, obj, "width", v8::Integer::NewFromUnsigned(isolate, t.GetWidth()));
|
|
1099
|
+
SetValue(isolate, obj, "height", v8::Integer::NewFromUnsigned(isolate, t.GetHeight()));
|
|
1100
|
+
SetMethod(isolate, obj, "createView", Texture_CreateView);
|
|
1101
|
+
SetMethod(isolate, obj, "destroy", Texture_Destroy);
|
|
1102
|
+
return obj;
|
|
1103
|
+
}
|
|
1104
|
+
|
|
1105
|
+
static v8::Local<v8::Object> WrapEncoder(v8::Isolate* isolate, wgpu::CommandEncoder encoder)
|
|
1106
|
+
{
|
|
1107
|
+
auto obj = WrapWith(isolate, Tmpl(isolate).commandEncoder, std::move(encoder));
|
|
1108
|
+
SetMethod(isolate, obj, "beginRenderPass", Encoder_BeginRenderPass);
|
|
1109
|
+
SetMethod(isolate, obj, "finish", Encoder_Finish);
|
|
1110
|
+
SetMethod(isolate, obj, "copyBufferToBuffer", Encoder_CopyBufferToBuffer);
|
|
1111
|
+
SetMethod(isolate, obj, "copyTextureToTexture", Encoder_CopyTextureToTexture);
|
|
1112
|
+
SetMethod(isolate, obj, "copyTextureToBuffer", Encoder_CopyTextureToBuffer);
|
|
1113
|
+
return obj;
|
|
1114
|
+
}
|
|
1115
|
+
|
|
1116
|
+
static v8::Local<v8::Object> WrapPipeline(v8::Isolate* isolate, wgpu::RenderPipeline pipeline)
|
|
1117
|
+
{
|
|
1118
|
+
auto obj = WrapWith(isolate, Tmpl(isolate).renderPipeline, std::move(pipeline));
|
|
1119
|
+
SetMethod(isolate, obj, "getBindGroupLayout", Pipeline_GetBindGroupLayout);
|
|
1120
|
+
return obj;
|
|
1121
|
+
}
|
|
1122
|
+
|
|
1123
|
+
// ---------------------------------------------------------------------------
|
|
1124
|
+
// GPUDevice / GPUQueue / GPUAdapter のラップ
|
|
1125
|
+
// ---------------------------------------------------------------------------
|
|
1126
|
+
static v8::Local<v8::Object> WrapQueue(v8::Isolate* isolate, wgpu::Queue queue)
|
|
1127
|
+
{
|
|
1128
|
+
auto obj = WrapWith(isolate, Tmpl(isolate).queue, std::move(queue));
|
|
1129
|
+
SetMethod(isolate, obj, "submit", Queue_Submit);
|
|
1130
|
+
SetMethod(isolate, obj, "writeBuffer", Queue_WriteBuffer);
|
|
1131
|
+
SetMethod(isolate, obj, "writeTexture", Queue_WriteTexture);
|
|
1132
|
+
SetMethod(isolate, obj, "copyExternalImageToTexture", Queue_CopyExternalImageToTexture);
|
|
1133
|
+
return obj;
|
|
1134
|
+
}
|
|
1135
|
+
|
|
1136
|
+
static v8::Local<v8::Object> WrapDevice(v8::Isolate* isolate, wgpu::Device device)
|
|
1137
|
+
{
|
|
1138
|
+
auto obj = WrapWith(isolate, Tmpl(isolate).device, device);
|
|
1139
|
+
SetMethod(isolate, obj, "createBuffer", Device_CreateBuffer);
|
|
1140
|
+
SetMethod(isolate, obj, "createTexture", Device_CreateTexture);
|
|
1141
|
+
SetMethod(isolate, obj, "createSampler", Device_CreateSampler);
|
|
1142
|
+
SetMethod(isolate, obj, "createShaderModule", Device_CreateShaderModule);
|
|
1143
|
+
SetMethod(isolate, obj, "createBindGroupLayout", Device_CreateBindGroupLayout);
|
|
1144
|
+
SetMethod(isolate, obj, "createBindGroup", Device_CreateBindGroup);
|
|
1145
|
+
SetMethod(isolate, obj, "createPipelineLayout", Device_CreatePipelineLayout);
|
|
1146
|
+
SetMethod(isolate, obj, "createRenderPipeline", Device_CreateRenderPipeline);
|
|
1147
|
+
SetMethod(isolate, obj, "createCommandEncoder", Device_CreateCommandEncoder);
|
|
1148
|
+
SetValue(isolate, obj, "queue", WrapQueue(isolate, device.GetQueue()));
|
|
1149
|
+
SetValue(isolate, obj, "features", v8::Object::New(isolate));
|
|
1150
|
+
|
|
1151
|
+
// limits: player は maxTextureDimension2D で描画最大サイズを決めるため実値を返す。
|
|
1152
|
+
// GetLimits の戻り値型は Dawn バージョン差があるため値でガードする(0 なら保証最小値)。
|
|
1153
|
+
v8::Local<v8::Object> limits = v8::Object::New(isolate);
|
|
1154
|
+
wgpu::Limits l = {};
|
|
1155
|
+
device.GetLimits(&l);
|
|
1156
|
+
auto orDefault = [](uint32_t v, uint32_t fb) { return v ? v : fb; };
|
|
1157
|
+
SetValue(isolate, limits, "maxTextureDimension1D", v8::Integer::NewFromUnsigned(isolate, orDefault(l.maxTextureDimension1D, 8192)));
|
|
1158
|
+
SetValue(isolate, limits, "maxTextureDimension2D", v8::Integer::NewFromUnsigned(isolate, orDefault(l.maxTextureDimension2D, 8192)));
|
|
1159
|
+
SetValue(isolate, limits, "maxTextureDimension3D", v8::Integer::NewFromUnsigned(isolate, orDefault(l.maxTextureDimension3D, 2048)));
|
|
1160
|
+
SetValue(isolate, limits, "maxBindGroups", v8::Integer::NewFromUnsigned(isolate, orDefault(l.maxBindGroups, 4)));
|
|
1161
|
+
SetValue(isolate, limits, "maxBufferSize", v8::Number::New(isolate, static_cast<double>(l.maxBufferSize ? l.maxBufferSize : (256u << 20))));
|
|
1162
|
+
SetValue(isolate, limits, "maxVertexBuffers", v8::Integer::NewFromUnsigned(isolate, orDefault(l.maxVertexBuffers, 8)));
|
|
1163
|
+
SetValue(isolate, limits, "maxVertexAttributes", v8::Integer::NewFromUnsigned(isolate, orDefault(l.maxVertexAttributes, 16)));
|
|
1164
|
+
SetValue(isolate, limits, "maxColorAttachments", v8::Integer::NewFromUnsigned(isolate, orDefault(l.maxColorAttachments, 8)));
|
|
1165
|
+
SetValue(isolate, obj, "limits", limits);
|
|
1166
|
+
return obj;
|
|
1167
|
+
}
|
|
1168
|
+
|
|
1169
|
+
// requestDevice() -> Promise<GPUDevice>
|
|
1170
|
+
static void Adapter_RequestDevice(const v8::FunctionCallbackInfo<v8::Value>& args)
|
|
1171
|
+
{
|
|
1172
|
+
v8::Isolate* isolate = args.GetIsolate();
|
|
1173
|
+
v8::Local<v8::Context> ctx = isolate->GetCurrentContext();
|
|
1174
|
+
DawnContext* gpu = HostContext::From(isolate)->gpu;
|
|
1175
|
+
|
|
1176
|
+
auto resolver = v8::Promise::Resolver::New(ctx).ToLocalChecked();
|
|
1177
|
+
args.GetReturnValue().Set(resolver->GetPromise());
|
|
1178
|
+
|
|
1179
|
+
// DawnContext が単一 device を保持。取得済みならそれをラップする。
|
|
1180
|
+
if (!gpu->ready() && !gpu->AcquireDevice()) {
|
|
1181
|
+
resolver->Reject(ctx, v8::Exception::Error(Str(isolate, "requestDevice failed"))).Check();
|
|
1182
|
+
return;
|
|
1183
|
+
}
|
|
1184
|
+
resolver->Resolve(ctx, WrapDevice(isolate, gpu->device())).Check();
|
|
1185
|
+
}
|
|
1186
|
+
|
|
1187
|
+
// navigator.gpu.requestAdapter() -> Promise<GPUAdapter>
|
|
1188
|
+
static void GPU_RequestAdapter(const v8::FunctionCallbackInfo<v8::Value>& args)
|
|
1189
|
+
{
|
|
1190
|
+
v8::Isolate* isolate = args.GetIsolate();
|
|
1191
|
+
v8::Local<v8::Context> ctx = isolate->GetCurrentContext();
|
|
1192
|
+
DawnContext* gpu = HostContext::From(isolate)->gpu;
|
|
1193
|
+
|
|
1194
|
+
auto resolver = v8::Promise::Resolver::New(ctx).ToLocalChecked();
|
|
1195
|
+
args.GetReturnValue().Set(resolver->GetPromise());
|
|
1196
|
+
|
|
1197
|
+
if (!gpu->ready() && !gpu->AcquireDevice()) {
|
|
1198
|
+
resolver->Resolve(ctx, v8::Null(isolate)).Check();
|
|
1199
|
+
return;
|
|
1200
|
+
}
|
|
1201
|
+
|
|
1202
|
+
auto adapter = WrapWith(isolate, Tmpl(isolate).adapter, gpu->adapter());
|
|
1203
|
+
SetMethod(isolate, adapter, "requestDevice", Adapter_RequestDevice);
|
|
1204
|
+
SetValue(isolate, adapter, "features", v8::Object::New(isolate));
|
|
1205
|
+
SetValue(isolate, adapter, "limits", v8::Object::New(isolate));
|
|
1206
|
+
resolver->Resolve(ctx, adapter).Check();
|
|
1207
|
+
}
|
|
1208
|
+
|
|
1209
|
+
static void GPU_GetPreferredCanvasFormat(const v8::FunctionCallbackInfo<v8::Value>& args)
|
|
1210
|
+
{
|
|
1211
|
+
Ctx_GetConfiguredFormat(args);
|
|
1212
|
+
}
|
|
1213
|
+
|
|
1214
|
+
// ---------------------------------------------------------------------------
|
|
1215
|
+
// テンプレート初期化 + 定数 + navigator.gpu の設置
|
|
1216
|
+
// ---------------------------------------------------------------------------
|
|
1217
|
+
static void InitTemplates(v8::Isolate* isolate)
|
|
1218
|
+
{
|
|
1219
|
+
Templates& t = Tmpl(isolate);
|
|
1220
|
+
auto make = [&](v8::Global<v8::ObjectTemplate>& g) {
|
|
1221
|
+
g.Reset(isolate, HandleTemplate(isolate));
|
|
1222
|
+
};
|
|
1223
|
+
make(t.adapter); make(t.device); make(t.queue); make(t.buffer); make(t.texture);
|
|
1224
|
+
make(t.textureView); make(t.sampler); make(t.shaderModule); make(t.bindGroupLayout);
|
|
1225
|
+
make(t.bindGroup); make(t.pipelineLayout); make(t.renderPipeline); make(t.commandEncoder);
|
|
1226
|
+
make(t.renderPass); make(t.commandBuffer); make(t.canvasContext);
|
|
1227
|
+
}
|
|
1228
|
+
|
|
1229
|
+
static void SetFlag(v8::Isolate* isolate, v8::Local<v8::Object> obj, const char* k, uint32_t v)
|
|
1230
|
+
{
|
|
1231
|
+
SetValue(isolate, obj, k, v8::Integer::NewFromUnsigned(isolate, v));
|
|
1232
|
+
}
|
|
1233
|
+
|
|
1234
|
+
} // namespace webgpu
|
|
1235
|
+
|
|
1236
|
+
// Bindings.h から呼ばれる公開関数
|
|
1237
|
+
void InstallWebGPU(v8::Isolate* isolate, v8::Local<v8::Object> global, HostContext* host)
|
|
1238
|
+
{
|
|
1239
|
+
using namespace next2d::webgpu;
|
|
1240
|
+
v8::Local<v8::Context> ctx = isolate->GetCurrentContext();
|
|
1241
|
+
|
|
1242
|
+
InitTemplates(isolate);
|
|
1243
|
+
|
|
1244
|
+
// navigator.gpu は WebGPU バックエンド時のみ公開する。
|
|
1245
|
+
// WebGL2 バックエンド(Switch 等)では navigator.gpu を出さず、player を
|
|
1246
|
+
// canvas.getContext('webgl2') 経路へフォールバックさせる。
|
|
1247
|
+
if (host->backend == GraphicsBackend::WebGPU) {
|
|
1248
|
+
// navigator は DomShims が生成する。存在しなければ作る。
|
|
1249
|
+
v8::Local<v8::Value> nav_val;
|
|
1250
|
+
v8::Local<v8::Object> navigator;
|
|
1251
|
+
if (global->Get(ctx, Str(isolate, "navigator")).ToLocal(&nav_val) && nav_val->IsObject()) {
|
|
1252
|
+
navigator = nav_val.As<v8::Object>();
|
|
1253
|
+
} else {
|
|
1254
|
+
navigator = v8::Object::New(isolate);
|
|
1255
|
+
SetValue(isolate, global, "navigator", navigator);
|
|
1256
|
+
}
|
|
1257
|
+
|
|
1258
|
+
v8::Local<v8::Object> gpu = v8::Object::New(isolate);
|
|
1259
|
+
SetMethod(isolate, gpu, "requestAdapter", GPU_RequestAdapter);
|
|
1260
|
+
SetMethod(isolate, gpu, "getPreferredCanvasFormat", GPU_GetPreferredCanvasFormat);
|
|
1261
|
+
SetValue(isolate, navigator, "gpu", gpu);
|
|
1262
|
+
}
|
|
1263
|
+
|
|
1264
|
+
// 使用フラグ定数群 (ブラウザが提供する GPU*Usage 等)
|
|
1265
|
+
auto usage = v8::Object::New(isolate);
|
|
1266
|
+
SetFlag(isolate, usage, "MAP_READ", 0x0001);
|
|
1267
|
+
SetFlag(isolate, usage, "MAP_WRITE", 0x0002);
|
|
1268
|
+
SetFlag(isolate, usage, "COPY_SRC", 0x0004);
|
|
1269
|
+
SetFlag(isolate, usage, "COPY_DST", 0x0008);
|
|
1270
|
+
SetFlag(isolate, usage, "INDEX", 0x0010);
|
|
1271
|
+
SetFlag(isolate, usage, "VERTEX", 0x0020);
|
|
1272
|
+
SetFlag(isolate, usage, "UNIFORM", 0x0040);
|
|
1273
|
+
SetFlag(isolate, usage, "STORAGE", 0x0080);
|
|
1274
|
+
SetFlag(isolate, usage, "INDIRECT", 0x0100);
|
|
1275
|
+
SetFlag(isolate, usage, "QUERY_RESOLVE", 0x0200);
|
|
1276
|
+
SetValue(isolate, global, "GPUBufferUsage", usage);
|
|
1277
|
+
|
|
1278
|
+
auto tex_usage = v8::Object::New(isolate);
|
|
1279
|
+
SetFlag(isolate, tex_usage, "COPY_SRC", 0x01);
|
|
1280
|
+
SetFlag(isolate, tex_usage, "COPY_DST", 0x02);
|
|
1281
|
+
SetFlag(isolate, tex_usage, "TEXTURE_BINDING", 0x04);
|
|
1282
|
+
SetFlag(isolate, tex_usage, "STORAGE_BINDING", 0x08);
|
|
1283
|
+
SetFlag(isolate, tex_usage, "RENDER_ATTACHMENT", 0x10);
|
|
1284
|
+
SetValue(isolate, global, "GPUTextureUsage", tex_usage);
|
|
1285
|
+
|
|
1286
|
+
auto stage = v8::Object::New(isolate);
|
|
1287
|
+
SetFlag(isolate, stage, "VERTEX", 0x1);
|
|
1288
|
+
SetFlag(isolate, stage, "FRAGMENT", 0x2);
|
|
1289
|
+
SetFlag(isolate, stage, "COMPUTE", 0x4);
|
|
1290
|
+
SetValue(isolate, global, "GPUShaderStage", stage);
|
|
1291
|
+
|
|
1292
|
+
auto color_write = v8::Object::New(isolate);
|
|
1293
|
+
SetFlag(isolate, color_write, "RED", 0x1);
|
|
1294
|
+
SetFlag(isolate, color_write, "GREEN", 0x2);
|
|
1295
|
+
SetFlag(isolate, color_write, "BLUE", 0x4);
|
|
1296
|
+
SetFlag(isolate, color_write, "ALPHA", 0x8);
|
|
1297
|
+
SetFlag(isolate, color_write, "ALL", 0xF);
|
|
1298
|
+
SetValue(isolate, global, "GPUColorWrite", color_write);
|
|
1299
|
+
|
|
1300
|
+
auto map_mode = v8::Object::New(isolate);
|
|
1301
|
+
SetFlag(isolate, map_mode, "READ", 0x1);
|
|
1302
|
+
SetFlag(isolate, map_mode, "WRITE", 0x2);
|
|
1303
|
+
SetValue(isolate, global, "GPUMapMode", map_mode);
|
|
1304
|
+
}
|
|
1305
|
+
|
|
1306
|
+
// Canvas.cpp から呼ばれる公開関数: canvas.getContext('webgpu') が返す
|
|
1307
|
+
// GPUCanvasContext を生成する (DawnContext のサーフェスを参照)。
|
|
1308
|
+
v8::Local<v8::Object> CreateWebGPUCanvasContext(v8::Isolate* isolate, HostContext* /*host*/)
|
|
1309
|
+
{
|
|
1310
|
+
using namespace next2d::webgpu;
|
|
1311
|
+
v8::Local<v8::Object> context = v8::Object::New(isolate);
|
|
1312
|
+
SetMethod(isolate, context, "configure", Ctx_Configure);
|
|
1313
|
+
SetMethod(isolate, context, "unconfigure", [](const v8::FunctionCallbackInfo<v8::Value>&) {});
|
|
1314
|
+
SetMethod(isolate, context, "getCurrentTexture", Ctx_GetCurrentTexture);
|
|
1315
|
+
return context;
|
|
1316
|
+
}
|
|
1317
|
+
|
|
1318
|
+
} // namespace next2d
|