From febcfc8f2dec0a113a0a8b70061bf825a2109206 Mon Sep 17 00:00:00 2001 From: Powei Feng Date: Wed, 21 Jan 2026 19:39:20 -0800 Subject: [PATCH] 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 --- filament/src/fg/FrameGraph.cpp | 4 +- filament/src/fg/FrameGraphId.h | 2 + filament/src/fg/FrameGraphRenderPass.h | 5 + filament/src/fg/PassNode.cpp | 49 ++++- filament/src/fg/details/PassNode.h | 16 +- .../include/fgviewer/FrameGraphInfo.h | 19 +- libs/fgviewer/src/FrameGraphInfo.cpp | 20 +- libs/fgviewer/src/JsonWriter.cpp | 42 +++- libs/fgviewer/web/app.js | 192 +++++++++++++++--- 9 files changed, 311 insertions(+), 38 deletions(-) diff --git a/filament/src/fg/FrameGraph.cpp b/filament/src/fg/FrameGraph.cpp index a954171ee4..7f201fce71 100644 --- a/filament/src/fg/FrameGraph.cpp +++ b/filament/src/fg/FrameGraph.cpp @@ -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 resources; diff --git a/filament/src/fg/FrameGraphId.h b/filament/src/fg/FrameGraphId.h index eb89174ad8..432e800745 100644 --- a/filament/src/fg/FrameGraphId.h +++ b/filament/src/fg/FrameGraphId.h @@ -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; } diff --git a/filament/src/fg/FrameGraphRenderPass.h b/filament/src/fg/FrameGraphRenderPass.h index b19acbda3d..e53cfda491 100644 --- a/filament/src/fg/FrameGraphRenderPass.h +++ b/filament/src/fg/FrameGraphRenderPass.h @@ -39,6 +39,11 @@ struct FrameGraphRenderPass { FrameGraphId stencil; FrameGraphId& operator[](size_t index) noexcept { + return const_cast&>( + static_cast(this)->operator[](index)); + } + + FrameGraphId const& operator[](size_t index) const noexcept { assert_invariant(index < ATTACHMENT_COUNT); if (index < backend::MRT::MAX_SUPPORTED_RENDER_TARGET_COUNT) { return color[index]; diff --git a/filament/src/fg/PassNode.cpp b/filament/src/fg/PassNode.cpp index 459d560a7a..5a7a01e168 100644 --- a/filament/src/fg/PassNode.cpp +++ b/filament/src/fg/PassNode.cpp @@ -175,7 +175,8 @@ void RenderPassNode::resolve() noexcept { rt.backend.params.flags.discardStart |= target; } VirtualResource* pResource = mFrameGraph.getResource(rt.descriptor.attachments[i]); - Resource* pTextureResource = static_cast*>(pResource); + Resource* pTextureResource = + static_cast*>(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 RenderPassNode::getRenderTargetInfo() const noexcept { + using namespace backend; + std::vector info; + info.reserve(mRenderTargetData.size()); + + for (auto const& rt: mRenderTargetData) { + RenderTargetInfo rtInfo; + + auto extractAttachmentInfo = [&](TargetBufferFlags flags, + std::vector& 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 diff --git a/filament/src/fg/details/PassNode.h b/filament/src/fg/details/PassNode.h index 3b91419ada..88cd02fdd1 100644 --- a/filament/src/fg/details/PassNode.h +++ b/filament/src/fg/details/PassNode.h @@ -23,9 +23,12 @@ #include "fg/FrameGraphRenderPass.h" #include "backend/DriverApiForward.h" - #include +#if FILAMENT_ENABLE_FGVIEWER +#include +#endif + #include #include #include @@ -60,6 +63,12 @@ public: virtual void resolve() noexcept = 0; utils::CString graphvizifyEdgeColor() const noexcept override; +#if FILAMENT_ENABLE_FGVIEWER + virtual std::vector + getRenderTargetInfo() const noexcept { + return {}; + } +#endif Vector devirtualize; // resources we need to create before executing Vector 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 + getRenderTargetInfo() const noexcept override; +#endif // constants const char* const mName = nullptr; diff --git a/libs/fgviewer/include/fgviewer/FrameGraphInfo.h b/libs/fgviewer/include/fgviewer/FrameGraphInfo.h index 2fcd44ce60..a4a6908843 100644 --- a/libs/fgviewer/include/fgviewer/FrameGraphInfo.h +++ b/libs/fgviewer/include/fgviewer/FrameGraphInfo.h @@ -39,14 +39,29 @@ public: bool operator==(const FrameGraphInfo& rhs) const; struct Pass { - Pass(utils::CString name, std::vector reads, - std::vector writes); + struct AttachmentInfo { + utils::CString name; + ResourceId id; + bool operator==(const AttachmentInfo& rhs) const; + }; + + struct RenderTargetInfo { + std::vector discardStart; + std::vector discardEnd; + std::vector clear; + bool operator==(const RenderTargetInfo& rhs) const; + }; + + Pass(uint32_t id, utils::CString name, std::vector reads, + std::vector writes, std::vector renderTargets = {}); bool operator==(const Pass& rhs) const; + uint32_t id; utils::CString name; std::vector reads; std::vector writes; + std::vector renderTargets; }; struct Resource { diff --git a/libs/fgviewer/src/FrameGraphInfo.cpp b/libs/fgviewer/src/FrameGraphInfo.cpp index 3a6f47a917..8abf97d24e 100644 --- a/libs/fgviewer/src/FrameGraphInfo.cpp +++ b/libs/fgviewer/src/FrameGraphInfo.cpp @@ -37,13 +37,25 @@ bool FrameGraphInfo::operator==(const FrameGraphInfo& rhs) const { && resources == rhs.resources; } -FrameGraphInfo::Pass::Pass(utils::CString name, std::vector reads, - std::vector writes): name(std::move(name)), +FrameGraphInfo::Pass::Pass(uint32_t id, utils::CString name, std::vector reads, + std::vector writes, std::vector 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, diff --git a/libs/fgviewer/src/JsonWriter.cpp b/libs/fgviewer/src/JsonWriter.cpp index 2f354bf66e..02dbd47b74 100644 --- a/libs/fgviewer/src/JsonWriter.cpp +++ b/libs/fgviewer/src/JsonWriter.cpp @@ -57,12 +57,49 @@ void writeResourceIds(std::ostream& os, const std::vector& resources } } +void writeRenderTargetInfo(std::ostream& os, + const std::vector& 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& 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& 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 << ","; diff --git a/libs/fgviewer/web/app.js b/libs/fgviewer/web/app.js index b2a1c04a15..6cac711fcd 100644 --- a/libs/fgviewer/web/app.js +++ b/libs/fgviewer/web/app.js @@ -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`${label}`; + } + render() { const renderFrameGraphs = (title) => { if (!this.framegraphs.length) @@ -316,10 +353,8 @@ class FrameGraphSidePanel extends LitElement { return html`
-
Name: ${currentResource.name}
-
-
-
ID: ${currentResource.id}
+
Name: ${currentResource.name} + [ID=${currentResource.id}]
${currentResource.properties.length > 0 ? html`
@@ -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` +
+
(${index})
+
    + ${resources.map(res => html` +
  • + ${this._formatResourceId(res.id)}: ${res.flags.join(", ")} +
  • + `)} +
+
+ `; + }; + + const joinResources = (ids) => { + return ids.map((id, i) => html` +
  • ${this._formatResourceId(id)}
  • `); + }; + + return html` + +
    +
    Name: ${currentPass.name} [ID=${currentPass.id}]
    +
    + ${currentPass.reads.length > 0 ? html` +
    +
    Reads:
    +
      + ${joinResources(currentPass.reads)} +
    +
    ` : nothing} + ${currentPass.renderTargets && currentPass.renderTargets.length > 0 ? + html`
    Writes (Render Targets):
    + ${currentPass.renderTargets.map((rt, i) => renderRenderTarget(rt, i))}` : nothing} +
    + `; + }; + return html`
    fgviewer
    ${renderFrameGraphs("Views") ?? nothing} ${renderResourceDetails("Resource Details") ?? nothing} + ${renderPassDetails("Pass Details") ?? nothing}
    `; } @@ -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`
    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`
    - ${this._renderResourceUsage(allPasses, resourceIds, DEFAULT_COLOR, lastRow)} + ${this._renderResourceUsage(allPasses, resourceIds, defaultColor, lastRow)}
    `; } + _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 {
    - ${allPasses.map(pass => html`
    -
    ${pass.name}
    `)} + ${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`
    +
    ${pass.name}
    `; + })}
    ${this._renderResourceRows(resources, allPasses)}
    @@ -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}"> @@ -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}">