Skip to content

Commit 688383b

Browse files
committed
#75 wip: xboxビルドテスト v65
1 parent f3cc179 commit 688383b

4 files changed

Lines changed: 58 additions & 2 deletions

File tree

templates/xbox/src/bindings/webgpu/WebGPUCommon.h

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -61,12 +61,15 @@ inline v8::Local<v8::ObjectTemplate> HandleTemplate(v8::Isolate* isolate)
6161
}
6262

6363
// --- JS オブジェクト読み取りヘルパー ------------------------------------
64+
// プロパティ名はキャッシュ済み internalized string (v8util::PropName) を使う。
65+
// ここは全ディスクリプタ解析の合流点で毎フレーム数千回通るため、名前 v8::String の
66+
// 毎回生成 (ヒープ確保 + ハッシュ) を排除する効果が大きい。
6467
inline v8::Local<v8::Value> Prop(v8::Isolate* isolate, v8::Local<v8::Object> obj,
6568
const char* key)
6669
{
6770
v8::Local<v8::Context> ctx = isolate->GetCurrentContext();
6871
v8::Local<v8::Value> v;
69-
if (obj->Get(ctx, v8util::Str(isolate, key)).ToLocal(&v)) {
72+
if (obj->Get(ctx, v8util::PropName(isolate, key)).ToLocal(&v)) {
7073
return v;
7174
}
7275
return v8::Undefined(isolate);

templates/xbox/src/gpu/DawnContext.cpp

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -117,6 +117,20 @@ bool DawnContext::AcquireDevice()
117117
device_desc.SetDeviceLostCallback(wgpu::CallbackMode::AllowProcessEvents, HandleDeviceLost);
118118
device_desc.SetUncapturedErrorCallback(HandleUncapturedError);
119119

120+
#ifdef NDEBUG
121+
// Release では Dawn の API 検証 (skip_validation) と robustness (OOB クランプ) を
122+
// 無効化する。両方とも全描画コマンドのエンコードで毎フレーム CPU を消費する
123+
// 安全網で、検証済みタイトルの出荷ビルドでは Chrome も同様に外す定番最適化。
124+
// Debug ビルドでは有効のままにして検証エラーを検出できるようにする
125+
// (エラーは HandleUncapturedError -> next2d-error.log へ出る)。
126+
// toggle 名は Dawn 本体 src/dawn/native/Toggles.cpp 定義 (いずれも ToggleStage::Device)。
127+
static const char* kReleaseToggles[] = {"skip_validation", "disable_robustness"};
128+
wgpu::DawnTogglesDescriptor device_toggles = {};
129+
device_toggles.enabledToggles = kReleaseToggles;
130+
device_toggles.enabledToggleCount = 2;
131+
device_desc.nextInChain = &device_toggles;
132+
#endif
133+
120134
wgpu::Future device_future = adapter_.RequestDevice(
121135
&device_desc,
122136
wgpu::CallbackMode::AllowProcessEvents,

templates/xbox/src/v8/V8Runtime.cpp

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -47,7 +47,11 @@ void V8Runtime::InitializeProcess(const char* exec_path)
4747
// - JS: --jitless (Ignition インタプリタのみ・RWX ページ無し)
4848
// - WebAssembly: --wasm-jitless (DrumBrake = V8 の wasm インタープリタ。
4949
// prebuilt V8 r2 は v8_enable_drumbrake=true でビルドされている)
50-
v8::V8::SetFlagsFromString("--jitless --wasm-jitless");
50+
// - --no-flush-bytecode: V8 は既定でしばらく実行されない関数のバイトコードを
51+
// 破棄し、次回実行時に再パースする (メモリ最適化)。ゲームでは画面遷移で
52+
// 久々に呼ばれる関数の再パースがフレームヒッチになるため無効化する
53+
// (ゲームバンドル数 MB 程度ならバイトコード常駐のメモリ増は許容範囲)。
54+
v8::V8::SetFlagsFromString("--jitless --wasm-jitless --no-flush-bytecode");
5155

5256
v8::V8::InitializeICUDefaultLocation(exec_path);
5357
v8::V8::InitializeExternalStartupData(exec_path);
@@ -80,6 +84,14 @@ bool V8Runtime::Initialize(HostContext* host)
8084
create_params_.array_buffer_allocator =
8185
v8::ArrayBuffer::Allocator::NewDefaultAllocator();
8286

87+
// 60fps のゲームはフレーム毎に短命オブジェクト (ディスクリプタ/一時配列) を
88+
// 大量生成する。young generation を既定 (十数 MB) から 64MB へ拡大して
89+
// scavenge (minor GC) の頻度を下げ、マイクロヒッチを減らす。
90+
// scavenge の停止時間は生存オブジェクト量に比例し空間サイズには比例しないため、
91+
// 拡大はほぼ純粋に頻度低減として効く。
92+
create_params_.constraints.set_max_young_generation_size_in_bytes(
93+
64 * 1024 * 1024);
94+
8395
isolate_ = v8::Isolate::New(create_params_);
8496
isolate_->SetData(kHostContextSlot, host);
8597
isolate_->SetData(kRuntimeSlot, this);

templates/xbox/src/v8/V8Util.h

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66
#include <fstream>
77
#include <string>
88
#include <string_view>
9+
#include <unordered_map>
910

1011
namespace next2d::v8util {
1112

@@ -18,6 +19,32 @@ inline v8::Local<v8::String> Str(v8::Isolate* isolate, std::string_view s)
1819
).ToLocalChecked();
1920
}
2021

22+
// プロパティ名 v8::String のキャッシュ。
23+
// バインディングのディスクリプタ解析 (webgpu::Prop/HasProp/U32 等) は毎フレーム
24+
// 数千回呼ばれ、その度に NewFromUtf8 が JS ヒープ確保 + ハッシュ計算をしていた。
25+
// internalized string (isolate 内で重複排除され、プロパティ検索がポインタ比較で済む)
26+
// を v8::Eternal で保持し、2 回目以降はハッシュマップ参照のみにする。
27+
// jitless では JS↔C++ 境界のコストが相対的に重いため、ここの削減が全体に効く。
28+
// キーは内容比較 (std::string) なので呼び出し元がリテラル以外を渡しても安全。
29+
// ホストは単一 Isolate 運用 (worker も同一 Isolate の別 Context) だが、
30+
// 念のため isolate が変わったらキャッシュを破棄する (Eternal は isolate 寿命に紐づく)。
31+
inline v8::Local<v8::String> PropName(v8::Isolate* isolate, const char* key)
32+
{
33+
static v8::Isolate* cached_isolate = nullptr;
34+
static std::unordered_map<std::string, v8::Eternal<v8::String>> cache;
35+
if (cached_isolate != isolate) {
36+
cache.clear();
37+
cached_isolate = isolate;
38+
}
39+
auto it = cache.find(key);
40+
if (it == cache.end()) {
41+
v8::Local<v8::String> s = v8::String::NewFromUtf8(
42+
isolate, key, v8::NewStringType::kInternalized).ToLocalChecked();
43+
it = cache.emplace(key, v8::Eternal<v8::String>(isolate, s)).first;
44+
}
45+
return it->second.Get(isolate);
46+
}
47+
2148
// v8::Value -> std::string (UTF-8)
2249
inline std::string ToStdString(v8::Isolate* isolate, v8::Local<v8::Value> value)
2350
{

0 commit comments

Comments
 (0)