fgviewer: add info in panel for render passes (#9618)

- Add plumbing to add more information about rendertargets
   (including discard flags and pass id) to the fgviewer pass
   struct.
 - Add UI to display information about a selected pass
 - Highlight a selected resource or pass
This commit is contained in:
Powei Feng
2026-01-21 19:39:20 -08:00
committed by GitHub
parent c04c387a89
commit febcfc8f2d
9 changed files with 311 additions and 38 deletions

View File

@@ -522,8 +522,8 @@ fgviewer::FrameGraphInfo FrameGraph::getFrameGraphInfo(const char *viewName) con
continue;
writes.push_back(resourceNode->resourceHandle.index);
}
passes.emplace_back(utils::CString(pass->getName()),
std::move(reads), std::move(writes));
passes.emplace_back(pass->getId(), utils::CString(pass->getName()),
std::move(reads), std::move(writes), pass->getRenderTargetInfo());
}
std::unordered_map<fgviewer::ResourceId, fgviewer::FrameGraphInfo::Resource> resources;

View File

@@ -64,6 +64,8 @@ public:
bool isInitialized() const noexcept { return index != UNINITIALIZED; }
uint16_t getIndex() const noexcept { return index; }
operator bool() const noexcept { return isInitialized(); }
void clear() noexcept { index = UNINITIALIZED; version = 0; }

View File

@@ -39,6 +39,11 @@ struct FrameGraphRenderPass {
FrameGraphId<FrameGraphTexture> stencil;
FrameGraphId<FrameGraphTexture>& operator[](size_t index) noexcept {
return const_cast<FrameGraphId<FrameGraphTexture>&>(
static_cast<const Attachments*>(this)->operator[](index));
}
FrameGraphId<FrameGraphTexture> const& operator[](size_t index) const noexcept {
assert_invariant(index < ATTACHMENT_COUNT);
if (index < backend::MRT::MAX_SUPPORTED_RENDER_TARGET_COUNT) {
return color[index];

View File

@@ -175,7 +175,8 @@ void RenderPassNode::resolve() noexcept {
rt.backend.params.flags.discardStart |= target;
}
VirtualResource* pResource = mFrameGraph.getResource(rt.descriptor.attachments[i]);
Resource<FrameGraphTexture>* pTextureResource = static_cast<Resource<FrameGraphTexture>*>(pResource);
Resource<FrameGraphTexture>* pTextureResource =
static_cast<Resource<FrameGraphTexture>*>(pResource);
pImportedRenderTarget = pImportedRenderTarget ?
pImportedRenderTarget : pResource->asImportedRenderTarget();
@@ -332,6 +333,52 @@ utils::CString RenderPassNode::graphvizify() const noexcept {
#endif
}
#if FILAMENT_ENABLE_FGVIEWER
using RenderTargetInfo = fgviewer::FrameGraphInfo::Pass::RenderTargetInfo;
using AttachmentInfo = fgviewer::FrameGraphInfo::Pass::AttachmentInfo;
std::vector<RenderTargetInfo> RenderPassNode::getRenderTargetInfo() const noexcept {
using namespace backend;
std::vector<RenderTargetInfo> info;
info.reserve(mRenderTargetData.size());
for (auto const& rt: mRenderTargetData) {
RenderTargetInfo rtInfo;
auto extractAttachmentInfo = [&](TargetBufferFlags flags,
std::vector<AttachmentInfo>& list) {
for (size_t i = 0; i < RenderPassData::ATTACHMENT_COUNT; ++i) {
TargetBufferFlags mask = getTargetBufferFlagsAt(i);
if (any(flags & mask)) {
FrameGraphHandle handle = rt.descriptor.attachments[i];
if (handle) {
const char* name = nullptr;
if (i < MRT::MAX_SUPPORTED_RENDER_TARGET_COUNT) name = "color";
else if (i == MRT::MAX_SUPPORTED_RENDER_TARGET_COUNT)
name = "depth";
else if (i == MRT::MAX_SUPPORTED_RENDER_TARGET_COUNT + 1)
name = "stencil";
utils::CString slotName(name);
if (i < MRT::MAX_SUPPORTED_RENDER_TARGET_COUNT) {
slotName += utils::to_string(i);
}
list.push_back({ slotName, handle.getIndex() });
}
}
}
};
extractAttachmentInfo(rt.backend.params.flags.discardStart, rtInfo.discardStart);
extractAttachmentInfo(rt.backend.params.flags.discardEnd, rtInfo.discardEnd);
extractAttachmentInfo(rt.backend.params.flags.clear, rtInfo.clear);
info.push_back(std::move(rtInfo));
}
return info;
}
#endif
// ------------------------------------------------------------------------------------------------
PresentPassNode::PresentPassNode(FrameGraph& fg) noexcept

View File

@@ -23,9 +23,12 @@
#include "fg/FrameGraphRenderPass.h"
#include "backend/DriverApiForward.h"
#include <backend/TargetBufferInfo.h>
#if FILAMENT_ENABLE_FGVIEWER
#include <fgviewer/FrameGraphInfo.h>
#endif
#include <cstdint>
#include <unordered_set>
#include <vector>
@@ -60,6 +63,12 @@ public:
virtual void resolve() noexcept = 0;
utils::CString graphvizifyEdgeColor() const noexcept override;
#if FILAMENT_ENABLE_FGVIEWER
virtual std::vector<fgviewer::FrameGraphInfo::Pass::RenderTargetInfo>
getRenderTargetInfo() const noexcept {
return {};
}
#endif
Vector<VirtualResource*> devirtualize; // resources we need to create before executing
Vector<VirtualResource*> destroy; // resources we need to destroy after executing
};
@@ -93,6 +102,7 @@ public:
utils::StaticString name, FrameGraphRenderPass::Descriptor const& descriptor);
RenderPassData const* getRenderPassData(uint32_t id) const noexcept;
size_t getRenderTargetCount() const noexcept { return mRenderTargetData.size(); }
private:
// virtuals from DependencyGraph::Node
@@ -100,6 +110,10 @@ private:
utils::CString graphvizify() const noexcept override;
void execute(FrameGraphResources const& resources, backend::DriverApi& driver) noexcept override;
void resolve() noexcept override;
#if FILAMENT_ENABLE_FGVIEWER
std::vector<fgviewer::FrameGraphInfo::Pass::RenderTargetInfo>
getRenderTargetInfo() const noexcept override;
#endif
// constants
const char* const mName = nullptr;

View File

@@ -39,14 +39,29 @@ public:
bool operator==(const FrameGraphInfo& rhs) const;
struct Pass {
Pass(utils::CString name, std::vector<ResourceId> reads,
std::vector<ResourceId> writes);
struct AttachmentInfo {
utils::CString name;
ResourceId id;
bool operator==(const AttachmentInfo& rhs) const;
};
struct RenderTargetInfo {
std::vector<AttachmentInfo> discardStart;
std::vector<AttachmentInfo> discardEnd;
std::vector<AttachmentInfo> clear;
bool operator==(const RenderTargetInfo& rhs) const;
};
Pass(uint32_t id, utils::CString name, std::vector<ResourceId> reads,
std::vector<ResourceId> writes, std::vector<RenderTargetInfo> renderTargets = {});
bool operator==(const Pass& rhs) const;
uint32_t id;
utils::CString name;
std::vector<ResourceId> reads;
std::vector<ResourceId> writes;
std::vector<RenderTargetInfo> renderTargets;
};
struct Resource {

View File

@@ -37,13 +37,25 @@ bool FrameGraphInfo::operator==(const FrameGraphInfo& rhs) const {
&& resources == rhs.resources;
}
FrameGraphInfo::Pass::Pass(utils::CString name, std::vector<ResourceId> reads,
std::vector<ResourceId> writes): name(std::move(name)),
FrameGraphInfo::Pass::Pass(uint32_t id, utils::CString name, std::vector<ResourceId> reads,
std::vector<ResourceId> writes, std::vector<RenderTargetInfo> renderTargets):
id(id),
name(std::move(name)),
reads(std::move(reads)),
writes(std::move(writes)) {}
writes(std::move(writes)),
renderTargets(std::move(renderTargets)) {}
bool FrameGraphInfo::Pass::operator==(const Pass& rhs) const {
return name == rhs.name && reads == rhs.reads && writes == rhs.writes;
return id == rhs.id && name == rhs.name && reads == rhs.reads && writes == rhs.writes &&
renderTargets == rhs.renderTargets;
}
bool FrameGraphInfo::Pass::AttachmentInfo::operator==(const AttachmentInfo& rhs) const {
return name == rhs.name && id == rhs.id;
}
bool FrameGraphInfo::Pass::RenderTargetInfo::operator==(const RenderTargetInfo& rhs) const {
return discardStart == rhs.discardStart && discardEnd == rhs.discardEnd && clear == rhs.clear;
}
FrameGraphInfo::Resource::Resource(ResourceId id, utils::CString name,

View File

@@ -57,12 +57,49 @@ void writeResourceIds(std::ostream& os, const std::vector<ResourceId>& resources
}
}
void writeRenderTargetInfo(std::ostream& os,
const std::vector<FrameGraphInfo::Pass::RenderTargetInfo>& renderTargets) {
os << " \"renderTargets\": [\n";
for (size_t i = 0; i < renderTargets.size(); ++i) {
const auto& rt = renderTargets[i];
os << " {\n";
auto writeAttachmentInfo =
[&](const char* label,
const std::vector<FrameGraphInfo::Pass::AttachmentInfo>& attachments) {
os << " \"" << label << "\": [\n";
for (size_t k = 0; k < attachments.size(); ++k) {
const auto& att = attachments[k];
os << " { \"name\": ";
writeJSONString(os, att.name.c_str());
os << ", \"id\": " << att.id << " }";
if (k + 1 < attachments.size()) os << ",";
os << "\n";
}
os << " ]";
};
writeAttachmentInfo("discardStart", rt.discardStart);
os << ",\n";
writeAttachmentInfo("discardEnd", rt.discardEnd);
os << ",\n";
writeAttachmentInfo("clear", rt.clear);
os << "\n";
os << " }";
if (i + 1 < renderTargets.size()) os << ",";
os << "\n";
}
os << " ]\n";
}
void writePasses(std::ostream& os, const FrameGraphInfo& frameGraph) {
os << " \"passes\": [\n";
auto& passes = frameGraph.getPasses();
for (size_t i = 0; i < passes.size(); ++i) {
const FrameGraphInfo::Pass& pass = passes[i];
os << " {\n";
os << " \"id\": " << pass.id << ",\n";
os << " \"name\": ";
writeJSONString(os, pass.name.c_str());
os << ",\n";
@@ -75,7 +112,10 @@ void writePasses(std::ostream& os, const FrameGraphInfo& frameGraph) {
const std::vector<ResourceId>& writes = pass.writes;
os << " \"writes\": [";
writeResourceIds(os, writes);
os << "]\n";
os << "],\n";
writeRenderTargetInfo(os, pass.renderTargets);
os << "\n";
os << " }";
if (i + 1 < passes.size()) os << ",";

View File

@@ -28,11 +28,13 @@ const REGULAR_FONT_SIZE = 12;
// Constants for color operations
const READ_COLOR = '#aee1a6';
const WRITE_COLOR = '#df8e8e';
const NO_ACCESS_COLOR = '#d8dde754';
const NO_ACCESS_COLOR = '#bcbcbc';
const READ_WRITE_COLOR = '#ffeb99';
const DEFAULT_COLOR = '#ffffff';
const SUBRESOURCE_COLOR = '#d3d3d3';
const SELECTED_ROW_COLUMN_COLOR = "rgba(180,210,240,.35)";
// Constants for view mode toggle
const VIEW_TOGGLE_INACTIVE_COLOR = '#292929';
const VIEW_TOGGLE_UNSELECTED_COLOR = '#3f4cbe';
@@ -200,6 +202,13 @@ class FrameGraphSidePanel extends LitElement {
background-color: ${this.connected ? VIEW_TOGGLE_SELECTED_COLOR:VIEW_TOGGLE_INACTIVE_COLOR};
font-weight: bold;
}
.resource-link:hover {
text-decoration: underline;
}
.render-target-resource {
display: flex;
flex-direction: row;
}
`;
}
@@ -208,6 +217,7 @@ class FrameGraphSidePanel extends LitElement {
connected: {type: Boolean, attribute: 'connected'},
selectedFrameGraph: {type: String, attribute: 'selected-framegraph'},
selectedResourceId: {type: Number, attribute: 'selected-resource'},
selectedPassIndex: {type: Number, attribute: 'selected-pass'},
viewMode: {type: String, attribute: 'view-mode'},
database: {type: Object, state: true},
@@ -222,6 +232,7 @@ class FrameGraphSidePanel extends LitElement {
this.database = {};
this.viewMode = VIEW_MODE_TABLE;
this.selectedFrameGraph = '';
this.selectedPassIndex = -1;
}
updated(props) {
@@ -274,6 +285,32 @@ class FrameGraphSidePanel extends LitElement {
return null;
}
_findCurrentPass() {
if (!this.selectedFrameGraph || this.selectedPassIndex === -1 ||
this.selectedPassIndex === undefined) {
return null;
}
const passes = this.database[this.selectedFrameGraph]?.passes;
return passes ? passes[this.selectedPassIndex] : null;
}
_handleResourceLinkClick(ev, id) {
ev.stopPropagation();
this.dispatchEvent(new CustomEvent('select-resource', {
detail: id,
bubbles: true,
composed: true
}));
}
_formatResourceId(id) {
const resources = this.database[this.selectedFrameGraph]?.resources;
const resource = resources ? resources[id] : null;
const label = resource ? `${resource.name} [${id}]` : `[${id}]`;
return html`<span class="resource-link" style="cursor: pointer;"
@click="${(e) => this._handleResourceLinkClick(e, id)}">${label}</span>`;
}
render() {
const renderFrameGraphs = (title) => {
if (!this.framegraphs.length)
@@ -316,10 +353,8 @@ class FrameGraphSidePanel extends LitElement {
return html`
<menu-section title="${title}">
<div class="resource-content">
<div><b>Name:</b> ${currentResource.name}</div>
</div>
<div class="resource-content">
<div><b>ID:</b> ${currentResource.id}</div>
<div><b>Name:</b> ${currentResource.name}
<b>[ID=${currentResource.id}]</b></div>
</div>
${currentResource.properties.length > 0 ? html`
<div class="resource-content">
@@ -335,12 +370,76 @@ class FrameGraphSidePanel extends LitElement {
`;
};
const renderPassDetails = (title) => {
const currentPass = this._findCurrentPass();
if (!currentPass) return nothing;
const renderRenderTarget = (rt, index) => {
const resourceFlags = {}; // id -> { name, flags: [] }
const processList = (list, flagName) => {
if (!list) return;
for (const att of list) {
if (!resourceFlags[att.id]) {
resourceFlags[att.id] = { name: att.name, id: att.id, flags: [] };
}
resourceFlags[att.id].flags.push(flagName);
}
};
processList(rt.discardStart, "Discard Start");
processList(rt.discardEnd, "Discard End");
processList(rt.clear, "Clear");
const resources = Object.values(resourceFlags);
if (resources.length === 0) return nothing;
return html`
<div class="resource-content render-target-resource"
style="margin-top: 5px; border-top: 1px dashed #6f6f6f;">
<div>(${index})</div>
<ul style="margin:0;padding-inline-start:25px">
${resources.map(res => html`
<li>
${this._formatResourceId(res.id)}: ${res.flags.join(", ")}
</li>
`)}
</ul>
</div>
`;
};
const joinResources = (ids) => {
return ids.map((id, i) => html`
<li>${this._formatResourceId(id)}</li>`);
};
return html`
<menu-section title="${title}">
<div class="resource-content">
<div><b>Name:</b> ${currentPass.name} <b>[ID=${currentPass.id}]</b></div>
</div>
${currentPass.reads.length > 0 ? html`
<div class="resource-content">
<div><b>Reads:</b> </div>
<ul style="margin: 4px 0;">
${joinResources(currentPass.reads)}
</ul>
</div>` : nothing}
${currentPass.renderTargets && currentPass.renderTargets.length > 0 ?
html`<div><b>Writes (Render Targets):</b></div>
${currentPass.renderTargets.map((rt, i) => renderRenderTarget(rt, i))}` : nothing}
</menu-section>
`;
};
return html`
<style>${this.dynamicStyle()}</style>
<div class="container">
<div class="title">fgviewer</div>
${renderFrameGraphs("Views") ?? nothing}
${renderResourceDetails("Resource Details") ?? nothing}
${renderPassDetails("Pass Details") ?? nothing}
</div>
`;
}
@@ -439,6 +538,7 @@ class FrameGraphTable extends LitElement {
}
.selected {
text-decoration: underline;
font-weight: bold;
}
.sticky-col {
text-align: right;
@@ -457,6 +557,7 @@ class FrameGraphTable extends LitElement {
return {
frameGraphData: {type: Object, state: true}, // Expecting a JSON frame graph structure
selectedResourceId: {type: Number, attribute: 'selected-resource'},
selectedPassIndex: {type: Number, attribute: 'selected-pass'},
tooltipText: {type: String, state: true},
tooltipVisible: {type: Boolean, state: true},
tooltipX: {type: Number, state: true},
@@ -468,6 +569,7 @@ class FrameGraphTable extends LitElement {
super();
this.frameGraphData = null;
this.selectedResourceId = -1;
this.selectedPassIndex = -1;
this.expandedResourceSet = new Set();
this.subresourceToParent = {};
this._hoverTimeout = null;
@@ -494,7 +596,7 @@ class FrameGraphTable extends LitElement {
}
_getRowGridTemplateColumnsStyle(numColumns) {
let out = '165px ';
let out = '185px ';
const oneCol = '35px ';
for (let i = 0; i < numColumns; i++) {
out += oneCol;
@@ -517,15 +619,23 @@ class FrameGraphTable extends LitElement {
}
this.requestUpdate();
}
if (props.has('selectedResourceId')) {
const parentId = this.subresourceToParent[this.selectedResourceId];
if (parentId && !this.expandedResourceSet.has(parentId)) {
this.expandedResourceSet.add(parentId);
this.requestUpdate();
}
}
}
_getCellColor(type) {
_getCellColor(type, defaultColor) {
return {
[RESOURCE_USAGE_TYPE_READ]: READ_COLOR,
[RESOURCE_USAGE_TYPE_WRITE]: WRITE_COLOR,
[RESOURCE_USAGE_TYPE_NO_ACCESS]: NO_ACCESS_COLOR,
[RESOURCE_USAGE_TYPE_READ_WRITE]: READ_WRITE_COLOR
}[type] || DEFAULT_COLOR;
}[type] || defaultColor;
}
_toggleCollapse(resourceId) {
@@ -549,9 +659,10 @@ class FrameGraphTable extends LitElement {
_renderResourceUsage(allPasses, resourceIds, defaultColor, lastRow) {
const passLen = allPasses.length;
return allPasses.map((passData, index) => {
const isSelectedPass = index === this.selectedPassIndex;
const isRead = resourceIds.some(resourceId => passData?.reads.includes(resourceId));
const isWrite = resourceIds.some(resourceId => passData?.writes.includes(resourceId));
let type = null;
let restype = null;
const hasUsed = (passData) => {
return resourceIds.some(resourceId =>
@@ -561,24 +672,25 @@ class FrameGraphTable extends LitElement {
const hasBeenUsedBefore = allPasses.slice(0, index).some(hasUsed);
const willBeUsedLater = allPasses.slice(index + 1).some(hasUsed);
if (isRead && isWrite) type = RESOURCE_USAGE_TYPE_READ_WRITE;
else if (isRead) type = RESOURCE_USAGE_TYPE_READ;
else if (isWrite) type = RESOURCE_USAGE_TYPE_WRITE;
else if (hasBeenUsedBefore && willBeUsedLater) type = RESOURCE_USAGE_TYPE_NO_ACCESS;
if (isRead && isWrite) restype = RESOURCE_USAGE_TYPE_READ_WRITE;
else if (isRead) restype = RESOURCE_USAGE_TYPE_READ;
else if (isWrite) restype = RESOURCE_USAGE_TYPE_WRITE;
else if (hasBeenUsedBefore && willBeUsedLater) restype = RESOURCE_USAGE_TYPE_NO_ACCESS;
const lastPass = index == passLen - 1;
const borderStyle = '1px solid #a5a5a5';
const bgColor = this._getCellColor(type, defaultColor);
const bgColor = isSelectedPass ? this._getCellColor(restype, SELECTED_ROW_COLUMN_COLOR)
: this._getCellColor(restype, defaultColor);
const style = `background-color:${bgColor};` +
`border-left:${borderStyle};border-top:${borderStyle};` +
(lastPass ? `border-right:${borderStyle};` : '') +
(lastRow ? `border-bottom:${borderStyle};` : '');
`border-left:${borderStyle};border-top:${borderStyle};` +
(lastPass ? `border-right:${borderStyle};` : '') +
(lastRow ? `border-bottom:${borderStyle};` : '');
let tooltip = '';
if (type === RESOURCE_USAGE_TYPE_READ) tooltip = 'Read';
else if (type === RESOURCE_USAGE_TYPE_WRITE) tooltip = 'Write';
else if (type === RESOURCE_USAGE_TYPE_READ_WRITE) tooltip = 'Read-Write';
else if (type === RESOURCE_USAGE_TYPE_NO_ACCESS) tooltip = 'No Access';
if (restype === RESOURCE_USAGE_TYPE_READ) tooltip = 'Read';
else if (restype === RESOURCE_USAGE_TYPE_WRITE) tooltip = 'Write';
else if (restype === RESOURCE_USAGE_TYPE_READ_WRITE) tooltip = 'Read-Write';
else if (restype === RESOURCE_USAGE_TYPE_NO_ACCESS) tooltip = 'No Access';
return html`
<div class="grid-cell" style="${style}"
@@ -635,9 +747,11 @@ class FrameGraphTable extends LitElement {
groupColorStyle = "border-right:5px solid " + COLORS[colorIndex];
}
const isSelectedResource = resource.id === this.selectedResourceId;
const onClickResource = () => this._handleResourceClick(resource.id);
const selectedStyle = resource.id === this.selectedResourceId ? "selected" : "";
const selectedStyle = isSelectedResource ? "selected" : "";
const rowStyle = this._getRowGridTemplateColumnsStyle(allPasses.length);
const defaultColor = isSelectedResource ? SELECTED_ROW_COLUMN_COLOR : DEFAULT_COLOR;
return html`
<div class="grid-row" id="resource-${resource.id}" style="${rowStyle}">
<div class="grid-cell sticky-col resource ${selectedStyle}" style="${groupColorStyle}"
@@ -652,11 +766,19 @@ class FrameGraphTable extends LitElement {
${resource.name}
${hasSubresources && !isExpanded ? html`(${subresourceIds.length})` : nothing}
</div>
${this._renderResourceUsage(allPasses, resourceIds, DEFAULT_COLOR, lastRow)}
${this._renderResourceUsage(allPasses, resourceIds, defaultColor, lastRow)}
</div>
`;
}
_handlePassClick(index) {
this.dispatchEvent(new CustomEvent('select-pass', {
detail: index,
bubbles: true,
composed: true
}));
}
render() {
if (!this.frameGraphData?.passes || !this.frameGraphData?.resources)
return nothing;
@@ -670,8 +792,14 @@ class FrameGraphTable extends LitElement {
<div class="grid-row" style="${rowStyle}">
<div class="grid-cell" style="${colStyle}">
</div>
${allPasses.map(pass => html`<div class="grid-cell" style="border:1px solid rgba(0,0,0,0)">
<div class="pass-cell">${pass.name}</div></div>`)}
${allPasses.map((pass, index) => {
const isSelected = index === this.selectedPassIndex;
const gclass = isSelected ? "grid-cell selected" : "grid-cell";
const pclass = isSelected ? "pass-cell selected" : "pass-cell";
return html`<div class="${gclass}" style="border:1px solid rgba(0,0,0,0); cursor: pointer;"
@click="${() => this._handlePassClick(index)}">
<div class="${pclass}">${pass.name}</div></div>`;
})}
</div>
${this._renderResourceRows(resources, allPasses)}
</div>
@@ -819,6 +947,7 @@ class FrameGraphViewer extends LitElement {
this.database = {};
this.selectedFrameGraph = null;
this.selectedResourceId = -1;
this.selectedPassIndex = -1;
this.viewMode = VIEW_MODE_TABLE;
this.init();
@@ -830,7 +959,13 @@ class FrameGraphViewer extends LitElement {
this.addEventListener('select-resource',
(ev) => {
this.selectedResourceId = ev.detail;
this.selectedResourceId = this.selectedResourceId === ev.detail ? -1 : ev.detail;
}
);
this.addEventListener('select-pass',
(ev) => {
this.selectedPassIndex = this.selectedPassIndex === ev.detail ? -1 : ev.detail;
}
);
@@ -847,6 +982,7 @@ class FrameGraphViewer extends LitElement {
database: {type: Object, state: true},
selectedFrameGraph: {type: String, state: true},
selectedResourceId: {type: Number, state: true},
selectedPassIndex: {type: Number, state: true},
viewMode: {type: String, state: true},
}
}
@@ -867,6 +1003,7 @@ class FrameGraphViewer extends LitElement {
?connected="${this.connected}"
selected-framegraph="${this.selectedFrameGraph}"
selected-resource="${this.selectedResourceId}"
selected-pass="${this.selectedPassIndex}"
view-mode="${this.viewMode}">
</framegraph-sidepanel>
@@ -874,7 +1011,8 @@ class FrameGraphViewer extends LitElement {
style="display: ${this.viewMode === VIEW_MODE_TABLE ? 'block' : 'none'};"
?connected="${this.connected}"
selected-framegraph="${this.selectedFrameGraph}"
selected-resource="${this.selectedResourceId}">
selected-resource="${this.selectedResourceId}"
selected-pass="${this.selectedPassIndex}">
</framegraph-table>
<graphviz-view id="graphviz"