Files
filament/libs/fgviewer/web/api.js
Powei Feng 2ae4dc4c62 fgviewer: visualize intermediate buffers (#9862)
* Intermediate Buffer Visualization: Enabled live monitoring of internal
  `FrameGraph` render targets directly in the `fgviewer` web UI.
* HTTP Polling Architecture: Switched from WebSocket binary pushes to native
  `<img>` polling (`/api/image`)
* Robust Resource Tracking: Replaced string-based lookups with
  `(ViewId, ResourceId)` composite keys to prevent cross-view collisions and
  ensure accurate reads.
* Format Post-Processing: Extracted readback conversions (HDR tonemapping,
  depth normalization, MSAA downsampling, single-channel expansion) into
  `DebugServer`.
* UI Polish: Added a live-updating full-screen image modal and explicitly
  filtered internal debug passes from the Graphviz/JSON exports to prevent
  DOM thrashing.
* WIP: Currently Unsupported:
  * GL backend: failed with:
      OpenGL framebuffer error 0x8cd6 (GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT) in "readTexture" at line 4198
  * Mipmaps & Subresources: Reading specific mip levels or array layers is
    explicitly skipped.
  * Shadowmaps: Variance Shadow Maps (VSM) will physically evaluate to `0.0`
    and appear completely empty/black in scenes without active shadow
    casters (due to inverted-Z).
  * Stencil: Resolving and reading stencil buffer data is not supported by
    the backend.
* WIP: Untested outside of MacOS+metal/vk
2026-04-21 20:30:45 +00:00

88 lines
2.7 KiB
JavaScript

/*
* Copyright (C) 2025 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
// api.js encapsulates all the REST endpoints that the server provides
async function _fetchJson(uri) {
const response = await fetch(uri);
return await response.json();
}
async function _fetchText(uri) {
const response = await fetch(uri);
return await response.text();
}
async function fetchFrameGraphs() {
const fgJson = await _fetchJson("api/framegraphs")
const ret = {};
for (const fgInfo of fgJson) {
ret[fgInfo.fgid] = fgInfo;
}
return ret;
}
async function fetchFrameGraph(fgid) {
const fgInfo = await _fetchJson(`api/framegraph?fgid=${fgid}`);
fgInfo.fgid = fgid;
return fgInfo;
}
async function fetchMonitoredResources() {
return await _fetchJson(`api/monitor`);
}
async function clearMonitoredResources() {
const response = await fetch(`api/monitor/clear`, {
method: "POST"
});
return await response.json();
}
async function toggleMonitor(fgid, id, name, enabled) {
const response = await fetch(`api/monitor`, {
method: "POST",
headers: { "Content-Type": "application/json" },
body: JSON.stringify({ fgid: fgid, id: id, name: name, enabled: enabled })
});
return await response.json();
}
const STATUS_LOOP_TIMEOUT = 3000;
const STATUS_CONNECTED = 1;
const STATUS_DISCONNECTED = 2;
const STATUS_FRAMEGRAPH_UPDATED = 3;
// Status function should be of the form function(status, data)
async function statusLoop(isConnected, onStatus) {
// This is a hanging get except for when transition from disconnected to connected, which
// should return immediately.
try {
const fgid = await _fetchText("api/status" + (isConnected() ? '' : '?firstTime'));
// A first-time request returned successfully
if (fgid === '0') {
await onStatus(STATUS_CONNECTED);
} else if (fgid !== '1') {
await onStatus(STATUS_FRAMEGRAPH_UPDATED, fgid);
} // fgid == '1' is no-op, just loop again
statusLoop(isConnected, onStatus);
} catch {
onStatus(STATUS_DISCONNECTED);
setTimeout(() => statusLoop(isConnected, onStatus), STATUS_LOOP_TIMEOUT)
}
}